如何将 8 字节长整数的每个字节相加?

Posted

技术标签:

【中文标题】如何将 8 字节长整数的每个字节相加?【英文标题】:How to add each byte of an 8-byte long integer? 【发布时间】:2013-08-27 18:42:56 【问题描述】:

我正在学习如何在视频应用程序中使用英特尔 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;

【问题讨论】:

请添加您的代码和期望的结果 单个 8 字节整数? psadbw 其中另一个操作数为零。 或者......旧的“通过乘法求水平字节求和”的技巧 - ((PackedWord * 0x0101010101010101ULL) >> 56) 也不能工作吗? 另一个操作数为零的psadbw起作用了。 【参考方案1】:

根据@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 今天学习新知识。看起来它很容易适应 _uint128_t。 通常最好使用 SSE2,而不是 MMX,即使您只需要一个 64 位水平和,而不是两个。那么在返回之前您不需要 EMMS。 __m128i result = _mm_sad_epu8(_mm_cvtsi64x_si128(pw), _mm_setzero_si128); 应该编译成相同的 MOVQ / PXOR-zeroing / PSADBW / MOVD。我忘记了 64x / 64 内在函数中的哪一个可用于 32 位代码,但 MOVQ(作为从内存加载)绝对有效。【参考方案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);

与执行三个成对归约相比,这会产生更精简的代码。

【讨论】:

【参考方案3】:

我不是汇编专家,但这段代码在没有花哨的 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);

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

【讨论】:

以上是关于如何将 8 字节长整数的每个字节相加?的主要内容,如果未能解决你的问题,请参考以下文章

将 8 个字节转换为有符号长整数(64 位)

SSE指令:字节+短

如何将数组的每个元素与同一数组的其他元素相加?

将可变大小的字节数组转换为整数/长整数

用汇编语言 ,将片外RAM的1000H单元开始的100字节的数据相加,结果存于R7R6中

关于c语言超长正整数相加的问题,。求高手指教!!!!!