x86 - 无溢出的无符号字节总和减少,在 Intel 上使用 SSE2

标签 x86 sse simd sse2 sse3

我试图在 Intel i3 处理器上找到 32 个元素(每个 1 字节数据)的总和减少。我这样做了:

s=0; 
for (i=0; i<32; i++)
{
    s = s + a[i];
}  

但是,它需要更多时间,因为我的应用程序是一个需要更少时间的实时应用程序。 请注意,最终和可能超过 255。

有没有办法可以使用低级 SIMD SSE2 指令来实现这一点?不幸的是,我从未使用过 SSE。为此,我尝试搜索 sse2 函数,但它也不可用。是否(sse)保证减少如此小规模问题的计算时间?

有什么建议吗??

注意:我已经使用 OpenCL 和 CUDA 实现了类似的算法,并且效果很好,但仅当问题规模很大时。对于小型问题,开销成本更高。不确定它在 SSE 上如何运作

最佳答案

您可以滥用 PSADBW快速计算小的水平和。

像这样:(未测试)

pxor xmm0, xmm0
psadbw xmm0, [a + 0]
pxor xmm1, xmm1
psadbw xmm1, [a + 16]
paddw xmm0, xmm1
pshufd xmm1, xmm0, 2
paddw xmm0, xmm1 ; low word in xmm0 is the total sum

尝试的内在函数版本:

我从不使用内在函数,所以这段代码可能毫无意义。不过拆机看起来还可以。

uint16_t sum_32(const uint8_t a[32])
{
    __m128i zero = _mm_xor_si128(zero, zero);
    __m128i sum0 = _mm_sad_epu8(
                        zero,
                        _mm_load_si128(reinterpret_cast<const __m128i*>(a)));
    __m128i sum1 = _mm_sad_epu8(
                        zero,
                        _mm_load_si128(reinterpret_cast<const __m128i*>(&a[16])));
    __m128i sum2 = _mm_add_epi16(sum0, sum1);
    __m128i totalsum = _mm_add_epi16(sum2, _mm_shuffle_epi32(sum2, 2));
    return totalsum.m128i_u16[0];
}

关于x86 - 无溢出的无符号字节总和减少,在 Intel 上使用 SSE2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10932550/

相关文章:

c++ - 使用内嵌 asm 编写一个带有 2 个比较的 for 循环

c - 更快的测试和清除位

assembly - 运行用 NASM 编写的 Win32 应用程序会导致 'This app cant run on your pc' 错误

c - 动态创建适当对齐的 C 结构内存内容

optimization - 利用 64 位寄存器的最酷的多操作技巧? (无 SIMD/SSE/AVX)

c++ - 用于 C++/SSE 代码的高效 NEON 内在函数

optimization - 近似 log10[x^k0 + k1]

c++ - 为什么在 CPU 上进行线程化浮点计算会使它们花费更长的时间?

x86 - 如何从 16 x 8 位 __m128i 值中提取 32 x 4 位整数

c - 哪个更快?