有没有办法在AVX上模拟_m256类型的整数按位运算?

时间:2013-12-11 19:03:15

标签: c++ c integer sse avx

我有一个布尔表达式,我已设法在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支持才能启用此功能?

2 个答案:

答案 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
}

当然,正如神秘指出这可能不值得做,但这并不意味着你不能这样做。