c++ - SIMD/SSE : How to check that all vector elements are non-zero

标签 c++ c gcc vectorization simd

我需要检查所有 vector 元素是否非零。到目前为止,我找到了以下解决方案。有一个更好的方法吗?我在 Linux/x86_64 上使用 gcc 4.8.2,指令高达 SSE4.2。

typedef char ChrVect __attribute__((vector_size(16), aligned(16)));

inline bool testNonzero(ChrVect vect)
{
    const ChrVect vzero = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    return (0 == (__int128_t)(vzero == vect));
}

更新:上面的代码被编译为以下汇编代码(当编译为非内联函数时):

movdqa  %xmm0, -24(%rsp)
pxor    %xmm0, %xmm0
pcmpeqb -24(%rsp), %xmm0
movdqa  %xmm0, -24(%rsp)
movq    -24(%rsp), %rax
orq -16(%rsp), %rax
sete    %al
ret

最佳答案

使用直接的 SSE 内在函数,您可以这样做:

inline bool testNonzero(__m128i v)
{
    __m128i vcmp = _mm_cmpeq_epi8(v, _mm_setzero_si128());
#if __SSE4_1__  // for SSE 4.1 and later use PTEST
    return _mm_testz_si128(vcmp, vcmp);
#else           // for older SSE use PMOVMSKB
    uint32_t mask = _mm_movemask_epi8(vcmp);
    return (mask == 0);
#endif
}

我建议查看您的编译器当前为现有代码生成的内容,然后使用内部函数将其与此版本进行比较,看看是否存在任何显着差异。

使用 SSE3 (clang -O3 -msse3) 对于上述函数,我得到以下结果:

pxor    %xmm1, %xmm1
pcmpeqb %xmm1, %xmm0
pmovmskb    %xmm0, %ecx
testl   %ecx, %ecx

SSE4 版本(clang -O3 -msse4.1)产生:

pxor    %xmm1, %xmm1
pcmpeqb %xmm1, %xmm0
ptest   %xmm0, %xmm0

请注意,xmm1 的归零通常会被提升到包含此函数的任何循环之外,因此在循环内使用时,上述序列应减少一条指令。

关于c++ - SIMD/SSE : How to check that all vector elements are non-zero,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34155897/

相关文章:

c++ - 将静态 Qt 库链接到 C 程序

c++ - "C/C++"不是说错了吗?

c - C中MD5的实现

c++ - Boost字符串算法错误

c++ - 从 WIC 图像 C++ 获取 RGB

c++ - VS2017跨平台项目未将C++ 17设置为语言标准

C++ : integer constant is too large for its type

linux - linux 和 windows 中的不同内存分配?

运行时的 C++ lambda 实现

c - 共享内存段中的链表