2

我正在学习如何在视频应用程序中使用英特尔 MMX 和 SSE 指令。我有一个 8 字节的字,我想将所有 8 个字节相加并生成一个整数作为结果。直接的方法是一系列 7 班次和加法,但这很慢。最快的方法是什么?是否有针对此的 MMX 或 SSE 指令?

这是这样做的缓慢方式

unsigned long PackedWord = whatever....
int byte1 = 0xff & (PackedWord);
int byte2 = 0xff & (PackedWord >> 8);
int byte3 = 0xff & (PackedWord >> 16);
int byte4 = 0xff & (PackedWord >> 24);
int byte5 = 0xff & (PackedWord >> 32);
int byte6 = 0xff & (PackedWord >> 40);
int byte7 = 0xff & (PackedWord >> 48);
int byte8 = 0xff & (PackedWord >> 56);
int sum = byte1 + byte2 + byte3 + byte4 + byte5 + byte6 + byte7 + byte8;
4

3 回答 3

5

根据@harold 的建议,您需要类似:

#include <emmintrin.h>

inline int bytesum(uint64_t pw)
{
  __m64 result = _mm_sad_pu8(*((__m64*) &pw), (__m64) 0LLU); // aka psadbw
  return _mm_cvtsi64_si32(result);
}
于 2013-08-27T19:40:32.127 回答
2

您可以在一对减少后通过水平相乘来做到这一点:

uint16_t bytesum(uint64_t x) {
    uint64_t pair_bits = 0x0001000100010001LLU;
    uint64_t mask = pair_bits * 0xFF;

    uint64_t pair_sum = (x & mask) + ((x >> 8) & mask);
    return (pair_sum * pair_bits) >> (64 - 16);
}

这产生的代码比执行三个成对归约要精简得多。

于 2016-09-23T23:35:43.460 回答
1

我不是汇编专家,但在没有花哨的 SIMD 指令的平台上,这段代码应该会快一点:

#include <stdint.h>

int bytesum(uint64_t pw) {
    uint64_t a, b, mask;

    mask = 0x00ff00ff00ff00ffLLU;
    a = (pw >> 8) & mask;
    b = pw & mask;
    pw = a + b;

    mask = 0x0000ffff0000ffffLLU;
    a = (pw >> 16) & mask;
    b = pw & mask;
    pw = a + b;

    return (pw >> 32) + (pw & 0xffffffffLLU);
}

这个想法是你首先添加每隔一个字节,然后是每隔一个单词,最后是每隔一个双重世界。

于 2013-08-27T19:24:00.660 回答