AVX2 64位无符号整数比较

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AVX2 64位无符号整数比较相关的知识,希望对你有一定的参考价值。

我想比较两个__m256i(4个打包的64位整数)。为此,我使用_mm256_cmpgt_epi64函数。

除了一些比较之外,该函数按预期工作,就好像函数没有考虑64位整数的最大位。如下面第二和第三次比较所示。

这里是一个MCVE,我希望a中的每个64位整数大于b的同行(因此cp应该是0xFFF...FFF):

#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("
");

    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;
}

然而,我的输出如下(按顺序cpab):

ffffffffffffffff 0000000000000000 0000000000000000 ffffffffffffffff 
000000000000000f f000000000000000 d00000000000000d 0f00000000000000 
0000000000000002 2000000000000000 2000000000000002 0200000000000000 

我不熟悉英特尔内在函数,所以如果有人能告诉我我做错了什么,那将不胜感激:)

答案

你的问题是_mm256_cmpgt_epi64比较了有符号整数,所以如果你在其中一个i64上设置了最高位,它就被认为是负数。例如,0xf000000000000000是负数,0x2000000000000000不是,而_mm256_cmpgt_epi64(正确地)告诉你后者更大。

它看起来不像有一个严格等效的函数来比较无符号整数,但你可以使用_mm256_cmpgt_epu64_mask,它返回一个__mmask8位字段。

编辑:忘了提及_mm256_cmpgt_epu64_mask需要AVX512,这可能不适合你。

以上是关于AVX2 64位无符号整数比较的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 sprintf 显示 64 位无符号整数?

使用 32 位无符号整数乘以 64 位数字的算法

8位无符号整数点分式版本

c# 默认赋值

在 32 位 iPhone 上处理 64 位整数

如何将两个32位整数组合成一个64位整数?