C ++ AVX2内在函数非标准大小

问题描述 投票:3回答:1

我正在尝试在C ++中使用AVX2内在函数。我正在使用打包到__m256中的花车。有8个浮点数可以容纳在寄存器中。但是如果我的浮点数少于8个,比如说我有5个浮点数,那该怎么办,在这种情况下,较低的3个浮点数具有垃圾值。

float a[5] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
float b[5] = {2.0f, 3.0f, 4.0f, 5.0f, 6.0f};

__m256 _a = _mm256_loadu_ps(a);
__m256 _b = _mm256_loadu_ps(b);

__m256 _c = _mm256_div_ps(_a, _b);

for(int i=0; i<8; ++i)
    cout << _c[i] << endl;

我在下面的屏幕截图中得到的结果:

“结果”

有什么方法可以将结果中的最后3个数字设为0?我不想运行循环,因为那样会破坏使用AVX的目的。另外,浮点数(在这种情况下为5)是可变的。

我是AVX的新手,真的很需要帮助。

在更大的问题中,我从数据流中读取了数组,因此事先不知道数组的大小,以便能够在不运行循环的情况下在数组末尾附加0。

c++ simd intrinsics avx avx2
1个回答
0
投票
float a[5] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
float b[5] = {2.0f, 3.0f, 4.0f, 5.0f, 6.0f};

__m256 _a = _mm256_loadu_ps(a);
__m256 _b = _mm256_loadu_ps(b);

这是未定义的行为,因为您正在读取数组之外的内容。

您可以使用_a清除_b_mm256_setzero_ps()中的所有元素:

__m256 _a = _mm256_setzero_ps;
__m256 _b = _mm256_setzero_ps;

将5个元素加载到__m256寄存器中比较麻烦。如果可能,可以用8个元素声明它。我相信C ++会用0.0f初始化值。

float a[8] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
float b[8] = {2.0f, 3.0f, 4.0f, 5.0f, 6.0f};

如果无法声明具有8个元素的数组,那么我可能会用GCC和Clang尝试类似的事情:

__m256 _a, _b;
memcpy(&_a, a, 5*sizeof(float));
memcpy(&_b, b, 5*sizeof(float));

您还可以复制到中间数组,并允许编译器进行优化:

float a[5] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
float b[5] = {2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
float t[0] = {0.0f};

memcpy(t, a, 5*sizeof(float));
__m256 _a = _mm256_loadu_ps(t);
memcpy(t, b, 5*sizeof(float));
__m256 _b = _mm256_loadu_ps(t);

还有一些AVX2广播说明可能对您有用。我相信您可以在前四个浮点数中加载__m256(即__m128)的上半部分,然后将一个元素设置为第五个浮点数。我没有很多广播到AVX2数据类型的经验,所以我没有示例代码。

最后一种可能性是加载一个完整的__m128,将一个元素设置为第二个__m128,然后将两个__m128合并为一个__m256。同样,我没有太多的经验,因此没有示例代码。

您还应该查看内在函数_mm_setzero(零个__m128),_mm_insert_ps(在__m128中设置一个浮点数),_mm256_inserti128_si256(组合__m128),_mm256_insertf128_ps(组合__m128 )和用于设置元素的朋友。

另请参见Intel Intrinsics Guide

© www.soinside.com 2019 - 2024. All rights reserved.