我有一个布尔表达式,我已设法在SSE2中实现。现在我想尝试在AVX中实现它,在并行性增加中利用额外的因子2(从128位SIMD类型到256)。但是,AVX不支持整数操作(AVX2可以使用,但我正在使用Sandy Bridge处理器,所以它目前不是一个选项)。但是,因为有AVX intrinsics for bitwise operations。我想我可以尝试将我的整数类型转换为浮点类型并查看它是否有效。
首次测试取得了成功:
__m256 ones = _mm256_set_ps(1,1,1,1,1,1,1,1);
__m256 twos = _mm256_set_ps(2,2,2,2,2,2,2,2);
__m256 result = _mm256_and_ps(ones, twos);
我正在按照我的意愿来训练所有的0。我们得到了2的结果,但是当我们得到11 XOR 4时,模拟地对这两个人进行了比较:
__m256 elevens = _mm256_set_ps(11,11,11,11,11,11,11,11);
__m256 fours = _mm256_set_ps(4,4,4,4,4,4,4,4);
__m256 result2 = _mm256_xor_ps(elevens, fours);
结果是6.46e-46(即接近0)而不是15.模拟地做11 OR 4给出的值为22而不是15应该是。我不明白为什么会这样。这是一个我错过的bug还是一些配置?
我实际上期待我使用float的假设,好像它们是整数不起作用,因为初始化为浮点值的整数可能实际上不是精确值而是近似值。但即便如此,我对结果感到惊讶。
有没有人能解决这个问题,还是我必须升级CPU以获得AVX2支持才能启用此功能?
答案 0 :(得分:7)
第一次测试是偶然的。
1作为浮点数是0x3f800000,2是0x40000000。一般来说,它不会那样工作。
但是你绝对可以做到这一点,你必须确保你正在使用正确的位模式。不要将整数转换为浮点数 - 重新解释它们。这对应于_mm256_castsi256_ps
这样的内在函数,或者将内存存储到内存中并将它们作为浮点数读取(这不会改变它们,通常只有数学运算关心浮点数意味着什么,其余的工作原始位模式,检查指令可以确保的例外列表。
答案 1 :(得分:4)
您不需要AVX2来使用AVX整数加载和存储操作:请参阅intel intrinsic guide。因此,您可以使用AVX加载整数,重新解释转换为浮点数,使用浮点按位运算,然后重新解释转换回int。重新解释转换不生成任何指令,它们只是让编译器满意。试试这个:
//compiled and ran on an Ivy Bridge system with AVX but without AVX2
#include <stdio.h>
#include <immintrin.h>
int main() {
int a[8] = {0, 2, 4, 6, 8, 10, 12, 14};
int b[8] = {1, 1, 1, 1, 1, 1, 1, 1};
int c[8];
__m256i a8 = _mm256_loadu_si256((__m256i*)a);
__m256i b8 = _mm256_loadu_si256((__m256i*)b);
__m256i c8 = _mm256_castps_si256(
_mm256_or_ps(_mm256_castsi256_ps(a8), _mm256_castsi256_ps(b8)));
_mm256_storeu_si256((__m256i*)c, c8);
for(int i=0; i<8; i++) printf("%d ", c[i]); printf("\n");
//output: 1 3 5 7 9 11 13 15
}
当然,正如神秘指出这可能不值得做,但这并不意味着你不能这样做。