C AVX2 64位无符号整数比较

C AVX2 64位无符号整数比较,c,integer,compare,avx2,C,Integer,Compare,Avx2,我试图比较两个\uuum256i(4个压缩64位整数)。为此,我使用函数 函数除了几个比较之外,工作正常,好像函数没有考虑64位整数的最大位。如第二次和第三次比较中所示 这里是一个MCVE,我希望a中的每个64位整数比b中的对等整数大(因此cp应该是0xFFF…FFF): 我不熟悉Intel Intrinsics函数,因此如果有人能告诉我我做错了什么,我将不胜感激:)您的问题是\u mm256\u cmpgt\u epi64比较有符号整数,因此如果您在其中一个i64上设置了最高有效位,它将被视为

我试图比较两个
\uuum256i
(4个压缩64位整数)。为此,我使用函数

函数除了几个比较之外,工作正常,好像函数没有考虑64位整数的最大位。如第二次和第三次比较中所示

这里是一个MCVE,我希望
a
中的每个64位整数比
b
中的对等整数大(因此
cp
应该是
0xFFF…FFF
):


我不熟悉Intel Intrinsics函数,因此如果有人能告诉我我做错了什么,我将不胜感激:)

您的问题是
\u mm256\u cmpgt\u epi64
比较有符号整数,因此如果您在其中一个i64上设置了最高有效位,它将被视为负数。例如,
0xf000000000000000
是负数,
0x2000000000000
不是负数,
\u mm256\u cmpgt\u epi64
(正确)告诉您后者更大

看起来没有一个严格等效的函数来比较无符号整数,但您可以使用
\u mm256\u cmpgt\u epu64\u mask
,它返回一个
\u mmask8
位字段


编辑:忘了提到
\u mm256\u cmpgt\u epu64\u mask
需要AVX512,您可能无法使用。

非常感谢您的解释,我没有想到这一点。您能告诉我如何打印/使用
\uu mask8
变量吗?我找不到关于它的任何文件。确实不能使用AVX512:
\uu mmask8
无符号字符的类型别名,因此使用
%x
打印格式设置程序应该可以。如果尝试使用cmp\u epu64\u掩码函数,我确实会出错<代码>错误:调用always_inline“\u mm256\u cmpgt\u epu64\u mask”时内联失败:目标特定选项不匹配
它似乎无法在我的计算机上运行,无论如何感谢您确定问题!要作为无符号整数进行比较,可以将
0x80000000000000
添加到
a
b
。并使用带符号的比较,例如,请参见。@wim:或更好,使用XOR而不是ADD(在Haswell/Broadwell上的更多端口上运行)。它是最高位,所以add=add不带进位。
#include <immintrin.h>
#include <x86intrin.h>
#include <stdio.h>
#include <inttypes.h>

// gcc mcve.c -mavx2 -madx && ./a.out

int print_avx2_hex256(__m256i ymm)
{
    const size_t n = sizeof(__m256i) / sizeof(u_int64_t);
    u_int64_t buffer[n];
    _mm256_storeu_si256((__m256i*)buffer, ymm);
    for (int i=0; i<n; ++i)
        printf("%016"PRIx64" ", buffer[i]);
    printf("\n");

    return 0;
}

int compare(__m256i a, __m256i b)
{
    __m256i cp = _mm256_cmpgt_epi64(a,b);

    print_avx2_hex256(cp); // Comparison
    print_avx2_hex256(a);
    print_avx2_hex256(b);

    return 0;
}

int main()
{
    u_int64_t _a[4] = {0xf, 0xf000000000000000, 0xd00000000000000d, 0x0f00000000000000};
    u_int64_t _b[4] = {0x2, 0x2000000000000000, 0x2000000000000002, 0x0200000000000000};

    __m256i a   = _mm256_setr_epi64x(_a[0], _a[1], _a[2], _a[3]);
    __m256i b   = _mm256_setr_epi64x(_b[0], _b[1], _b[2], _b[3]);

    compare(a,b);
    return 0;
}
ffffffffffffffff 0000000000000000 0000000000000000 ffffffffffffffff 
000000000000000f f000000000000000 d00000000000000d 0f00000000000000 
0000000000000002 2000000000000000 2000000000000002 0200000000000000