我可以正确比较avx中的零寄存器吗?

时间:2015-08-18 12:15:39

标签: c avx

我遇到了AVX内在指令_mm256_testc_pd()的一个非常奇怪的行为。 在这里,您可以看到此函数https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=AVX,AVX2&text=test&expand=5432

的说明

我在我的代码中使用它2次,预计看到类似的比较结果为零寄存器。

#include <immintrin.h>
#include <stdio.h>

int main(void)
{
    unsigned char arr[32] __attribute__ ((aligned (32)));

    __m256d a, zero;
    int res1, res2;

    memset(arr, 0 , 32);
    arr[0] = 0xff;
    arr[4] = 0xff;
    arr[8] = 0xff;
    arr[12] = 0xff;
    arr[16] = 0xff;
    arr[20] = 0xfd;
    arr[24] = 0xff;
    arr[28] = 0xff;


    zero = _mm256_setzero_pd();
    a = _mm256_load_pd((double *)arr);
    res1 = _mm256_testc_pd(zero, a);
    printf("res1 = %d\n" , res1);

    memset(arr, 0xff, 32);
    a = _mm256_load_pd((double *)arr);
    res2 =  _mm256_testc_pd(zero, a);
    printf("res2 = %d\n" , res2);
    return 0;
}

结果我得到了

res1 = 1
res2 = 0

有谁理解为什么会这样?我认为在这两种情况下a都不等于零。

更新
在评论讨论后,我的问题得到了解决,但我对函数_mm256_testc_si256和_mm256_testz_si256

有一点误解

例如:

unsigned char arr[32] __attribute__ ((aligned (32)));

    __m256d a, zero;

    int res1, res2;
    memset(arr, 0 , 32);

    arr[0] = 0x80;

    zero = _mm256_setzero_pd();
    a = _mm256_load_pd((double *)arr);

    res1 = _mm256_testc_si256(_mm256_castpd_si256(zero),_mm256_castpd_si256(a));
    res2 = _mm256_testz_si256(_mm256_castpd_si256(zero),_mm256_castpd_si256(a));
    printf("res1 = %d\n" , res1);
    printf("res2 = %d\n" , res2);

输出

res1 = 0
res2 = 1

我认为只有第一个是正确的。那么为什么这个函数产生不同的输出呢?

2 个答案:

答案 0 :(得分:4)

_mm256_testc_pd仅对每个双精度元素的符号位进行操作,因此观察到的行为是正确的。如果要在每个元素中测试双精度,请先使用合适的比较指令(例如_mm256_cmp_pd_CMP_xxx参数),然后使用_mm256_testc_pd_mm256_testz_pd之后,视您的具体要求而定。

答案 1 :(得分:0)

感谢Peter Cordes和其他所有人,我的问题的正确(和最美)解决方案是

res = _mm256_testz_si256(_mm256_castpd_si256(a), _mm256_castpd_si256(a))