我正在学习如何在视频应用中使用英特尔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;
答案 0 :(得分:4)
根据@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);
}
答案 1 :(得分:3)
你可以在一次成对缩减后用水平的乘法运算:
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);
}
这比产生三次成对缩减产生的代码更精简。
答案 2 :(得分: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);
}
这个想法是你首先添加每个其他字节,然后是每隔一个字,最后是每隔一个双世界。