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

Tob*_*999 5 c c++ integer sse avx

我有一个布尔表达式,我已设法在SSE2中实现.现在我想尝试在AVX中实现它,在并行性增加中利用额外的因子2(从128位SIMD类型到256).但是,AVX不支持整数操作(AVX2可以使用,但我正在使用Sandy Bridge处理器,因此它目前不是一个选项).但是,由于存在用于按位运算的AVX内在函数.我想我可以尝试将我的整数类型转换为浮点类型并查看它是否有效.

第一次测试是成功的:

__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);
Run Code Online (Sandbox Code Playgroud)

我正在按照自己的意愿来训练所有的0.模拟AND'ing两个而不是我得到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); 
Run Code Online (Sandbox Code Playgroud)

结果是6.46e-46(即接近0)而不是15.模拟地做11 OR 4给出的值为22而不是15应该是.我不明白为什么会这样.这是一个我错过的bug还是一些配置?

我实际上期待我使用float的假设,好像它们是整数不起作用,因为初始化为浮点值的整数可能实际上不是精确值而是近似值.但即便如此,我对我得到的结果感到惊讶.

有没有人有这个问题的解决方案或者我必须升级我的CPU才能获得AVX2支持吗?

har*_*old 7

第一次测试是偶然的.

1作为浮点数是0x3f800000,2是0x40000000.一般来说,它不会那样工作.

但你绝对可以做到这一点,你必须确保你正在使用正确的位模式.不要将整数转换为浮点数 - 重新解释它们.这对应于内在函数_mm256_castsi256_ps,或者将内存存储到内存中并将它们作为浮点数读取(这不会改变它们,通常只有数学运算关心浮点数的意思,其余的工作原始位模式,检查列表指令可以确保的例外情况).

  • @ Toby999但请注意,在所有当前的英特尔处理器上,按位逻辑指令的浮点版本的吞吐量仅为整数版本的1/3.所以,如果你是为了表现,你可能想三思而后行.除非你受到解码器带宽的限制,否则它可能会适得其反. (2认同)
  • 在Sandy和Ivy Bridge上,整数SSE按位逻辑可以在一个/周期内到达端口0,1或5中的任何一个.这是每个周期3.但是浮点SSE按位逻辑只能在一个/周期进入端口5.因此每个周期限制为1个.在Haswell,它是相同的,但它有AVX2 - 这使得这一点没有实际意义. (2认同)

Z b*_*son 5

您不需要AVX2即可使用AVX整数加载和存储操作:请参阅intel内部指南。因此,您可以使用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
}
Run Code Online (Sandbox Code Playgroud)

当然,正如Mystical指出的那样,这可能不值得做,但这并不意味着您做不到。