我正在尝试在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。
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
)和用于设置元素的朋友。