2012-08-29 61 views
3

是否有一個內部允許添加通道中的所有元素?我使用氖將8個數字相乘,我需要對結果進行求和。下面是一些意譯代碼來顯示目前我在做什麼(這也許可以被優化):添加通道中的所有元素

int16_t p[8], q[8], r[8]; 
int32_t sum; 
int16x8_t pneon, qneon, result; 

p[0] = some_number; 
p[1] = some_other_number; 
//etc etc 
pneon = vld1q_s16(p); 

q[0] = some_other_other_number; 
q[1] = some_other_other_other_number; 
//etc etc 
qneon = vld1q_s16(q); 
result = vmulq_s16(p,q); 
vst1q_s16(r,result); 
sum = ((int32_t) r[0] + (int32_t) r[1] + ... //etc); 

是否有「更好」的方式來做到這一點?

回答

0

像這樣的東西應該工作得最佳(注意:未測試)

const int16x4_t result_low = vget_low_s16(result); // Extract low 4 elements 
const int16x4_t result_high = vget_high_s16(result); // Extract high 4 elements 
const int32x4_t twopartsum = vaddl_s16(result_low, result_high); // Extend to 32 bits and add (4 partial 32-bit sums are formed) 
const int32x2_t twopartsum_low = vget_low_s32(twopartsum); // Extract 2 low 32-bit partial sums 
const int32x2_t twopartsum_high = vget_high_s32(twopartsum); // Extract 2 high 32-bit partial sums 
const int32x2_t fourpartsum = vadd_s32(twopartsum_low, twopartsum_high); // Add partial sums (2 partial 32-bit sum are formed) 
const int32x2_t eightpartsum = vpadd_s32(fourpartsum, fourpartsum); // Final reduction 
const int32_t sum = vget_lane_s32(eightpartsum, 0); // Move to general-purpose registers 
+0

'const int32x2_t eightpartsum = vpadd_s32(fourpartsum)'不起作用。我認爲它應該是'const int64x1 eightpartsum = vpaddl_s32(fourpartsum)'。儘管如此,我改變它,它編譯,但它實際上比我以前的方法慢得多.... – NOP

+0

我不認爲你會看到很多改善,除非這是一個嚴密的循環。我已經測試過這個,並且在100000的循環中,我總體上獲得了大約40%的改進。使用霓虹內在函數也很重要,使用最近的編譯器非常重要。我用過gcc 4.7.1。 – auselen

+0

vpadd_s32(fourpartsum)應該是vpadd_s32(四partsum,fourpartsum)。我編輯了這個帖子來修復它。 –

3

如果您所指定的新手臂64位架構,然後ADDV就是適合你的指令。

下面是代碼的外觀。

qneon = vld1q_s16(q); 
result = vmulq_s16(p,q); 
sum = vaddvq_s16(result); 

就是這樣。只需一條指令就可以總結向量寄存器中的所有通道。

不幸的是,這個指令在舊的32位arm架構中沒有特色。

相關問題