2013-08-27 80 views
2

我正在學習如何在視頻應用程序中使用英特爾MMX和SSE指令。我有一個8字節的單詞,我想添加所有8個字節併產生一個整數作爲結果。直截了當的方法是一系列7班倒並增加,但這是緩慢的。這樣做的最快方法是什麼?是否有MMX或SSE指令?如何添加一個8字節長整數的每個字節?

這是做

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

請添加您的代碼和渴望的結果 – tim

+0

單個8字節整數? – Jiminion

+3

'psadbw'其中操作數爲零。 – harold

回答

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); 
} 

這個想法是,你首先添加每一個字節,然後每隔一個字,最後添加其他所有的doubleworld。

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); 
} 
+0

+1今天學習新東西。看起來它很容易適應_uint128_t。 – chux

+1

即使您只需要一個64位水平和,而不是兩個,通常使用SSE2更好,而不是MMX。然後你在返回之前不需要EMMS。 '__m128i result = _mm_sad_epu8(_mm_cvtsi64x_si128(pw),_mm_setzero_si128);'應該編譯成相同的MOVQ/PXOR-zeroing/PSADBW/MOVD。我忘記了哪個'64x' /'64'內在函數可用於32位代碼,但MOVQ(作爲內存中的加載)肯定可用。 –

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); 
} 

這比產生三次成對減少產生更多精簡的代碼。

相關問題