<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > ARM處理器NEON編程及優(yōu)化技巧——處理剩余的元素

ARM處理器NEON編程及優(yōu)化技巧——處理剩余的元素

作者: 時(shí)間:2016-11-10 來(lái)源:網(wǎng)絡(luò ) 收藏
ARM的NEON協(xié)處理器技術(shù)是一個(gè)64/128-bit的混合SIMD架構,用于加速包括視頻編碼解碼、音頻解碼編碼、3D圖像、語(yǔ)音和圖像等多媒體和信號處理應用。本文主要介紹如何使用NEON的匯編程序來(lái)寫(xiě)SIMD的代碼,包括如何開(kāi)始NEON的開(kāi)發(fā),如何高效的利用NEON。首先會(huì )關(guān)注內存操作,即如何變更指令來(lái)靈活有效的加載和存儲數據。接下來(lái)是由于SIMD指令的應用而導致剩下的若干個(gè)單元的處理,然后是用一個(gè)矩陣乘法的例子來(lái)說(shuō)明用NEON來(lái)進(jìn)行SIMD優(yōu)化,最后關(guān)注如何用NEON來(lái)優(yōu)化各種各樣的移位操作,左移或者右移以及雙向移位等。本節主要介紹當輸入的數據大小不是一個(gè)向量大小的整數倍時(shí),怎么處理剩余的幾個(gè)元素,如把元素補齊到向量大小的整數倍的修復處理、重疊處理方式和單個(gè)元素處理方式。

關(guān)鍵字: ARM NEON Cortex-A8 cache 對齊

本文引用地址:http://dyxdggzs.com/article/201611/317425.htm

剩余的元素Leftovers

通常NEON會(huì )向量處理從4個(gè)到16個(gè)元素長(cháng)度的數據,如果你發(fā)現你的數組不是這個(gè)這個(gè)長(cháng)度的整數倍,你就需要單獨處理那些剩下來(lái)的幾個(gè)元素。如你每次可以使用NEON來(lái)加載處理并存儲8個(gè)元素的數據,但是你的數組有21個(gè)元素,你就需要先迭代兩次,然后第三次,你只剩下5個(gè)元素,此時(shí)應該如何處理呢?

Fixing Up修復處理方式

有三種處理方式來(lái)處理剩下來(lái)的元素,這些方法的需求、性能和代碼大小不同,下面順序介紹,從速度最快的方法開(kāi)始。

Larger Arrays更大的數組

如果改變你要處理的數組大小,比如增加數組大小到向量大小的整數倍,這樣就能在最后一次數據處理時(shí)也按照向量大小處理而不會(huì )把臨近的數據損壞。如上面的例子里,把數組大小增加到24個(gè)元素,這樣就能用NEON用3次迭代完成所有的數據處理而不會(huì )損壞周邊數據。

圖1. 填補數組到向量的整數個(gè)大小

注意事項Notes

  • 分配更大的數組需要更多的存儲空間,這會(huì )增加相當大的空間如果包含非常多的短數組;
  • 在數組后面填補的數據元素需要初始化為一個(gè)不會(huì )影響到結果的值,例如你要做加法,那這個(gè)新元素需要初始化為0以影響計算結果。
  • 一些情況下,可能沒(méi)法初始化填充的數據,無(wú)論填充什么都會(huì )影響計算的結果;

Code Fragment代碼片段實(shí)例

@ r0 是輸入的數組指針;

@ r1 是輸出數組指針;

@ r2 是數組數據的長(cháng)度;

假設數組長(cháng)度大于0,是向量大小的整數倍,并且大于或者等于數組的長(cháng)度;

add r2, r2, #7 @ 數據長(cháng)度加上向量長(cháng)度-1

lsr r2, r2, #3 @ 把數組長(cháng)度變成向量個(gè)數,即除以向量大小8

loop:

subs r2, r2, #1 @ 減少循環(huán)計數器個(gè)數

vld1.8 {d0}, [r0]! @ 從數組加載8個(gè)元素,從地址r0到寄存器d0,然后更新地址寄存器r0到下一個(gè)向量地址;

...

... @ 處理在d0寄存器的數據

...

vst1.8 {d0}, [r1]! @ 把8個(gè)結果元素保存到輸出數組,更新地址r1到下一個(gè)向量

bne loop @ 如果r2不等于0,繼續循環(huán)

Overlapping重疊計算

如果進(jìn)行數據處理的操作合適的話(huà),可以考慮把剩余部分的元素通過(guò)重疊計算的方式處理,這就會(huì )把某些重疊部分的元素計算兩次。如下面的例子里,第一次迭代計算元素0到7,第一次計算5到12,第三次計算13到20。從而第一次計算和第二次計算重疊的元素5到7就被計算了兩次。

arm.com/index.php?app=core&module=attach§ion=attach&attach_rel_module=blogentry&attach_id=419" rel="nofollow" >

圖2. 重疊向量,在橙色區域的數據計算兩次

Notes需要事項

  • 重疊處理只適用于需要處理的數組長(cháng)度不會(huì )隨著(zhù)每次迭代而改變的情況,但不適用于每次迭代結果改變的情況,如累加計算,這樣重疊部分的數據會(huì )被計算兩次;
  • 數組內元素的個(gè)數至少大于一次完整迭代的向量大??;

Code Fragment代碼片段實(shí)例

@ r0 是輸入的數組指針;

@ r1 是輸出數組指針;

@ r2 是數組數據的長(cháng)度;

假設數據操作冪等,并且數組長(cháng)度大于等于一個(gè)向量大小長(cháng)度。

ands r3, r2, #7 @ 計算每次處理完整個(gè)向量后剩余元素個(gè)數,使用與操作

beq loopsetup @ 如果剩余元素個(gè)數為0,則數組長(cháng)度是整數個(gè)向量大小,不用重疊計算,單獨處理第一個(gè)元素部分

vld1.8 {d0}, [r0], r3 @ 加載數組第一個(gè)向量,然后更新數組大小為剩余元素個(gè)數r3內保持

...

... @ 處理d0寄存器內的輸入數據

...

vst1.8 {d0}, [r1], r3 @ 保持8個(gè)元素到輸出數組,更新指針,然后開(kāi)始處理循環(huán)

loopsetup:

lsr r2, r2, #3 @ 把數組長(cháng)度除以8,計算循環(huán)迭代次數,若干元素跟第一次迭代的重疊

loop:

subs r2, r2, #1 @ 減少循環(huán)計數器個(gè)數

vld1.8 {d0}, [r0]! @ 從數組加載8個(gè)元素,從地址r0到寄存器d0,然后更新地址寄存器r0到下一個(gè)向量地址;

...

... @ 處理在d0寄存器的數據

...

vst1.8 {d0}, [r1]! @ 把8個(gè)結果元素保存到輸出數組,更新地址r1到下一個(gè)向量

bne loop @ 如果r2不等于0,繼續循環(huán)

單個(gè)元素的計算過(guò)程Single Elements

NEON提供了能處理向量里的單一元素的加載和存儲指令,用這些指令,你能加載包含一個(gè)元素的部分向量,處理它然后把結果保存到內存。如下面的例子,前兩次的迭代處理跟前面類(lèi)似,處理元素0到7以及8到15,剩下的5個(gè)元素可以在第三次迭代處理,加載處理并存儲單一的元素。

圖3. 處理單一的元素實(shí)例

注意事項

  • 這種方法比前面的兩種方法速度要慢,每個(gè)元素的處理都需要單獨進(jìn)行;
  • 這種的剩余元素處理方法需要兩個(gè)迭代循環(huán),第一個(gè)處理向量的循環(huán),還有處理剩余元素的循環(huán),這會(huì )增加代碼大??;
  • NEON的單一元素加載只改變目標元素的值,而保留其他的元素不變,如果你向量計算的指令會(huì )在一個(gè)向量間反復計算,如VPADD,這些寄存器需要在第一個(gè)元素加載時(shí)初始化。

代碼片段

@ r0 是輸入的數組指針;

@ r1 是輸出數組指針;

@ r2 是數組數據的長(cháng)度;

lsrs r3, r2, #3 @ 計算向量循環(huán)迭代的次數

beq singlesetup @ 如果沒(méi)有完整的一次迭代向量計算,則跳轉到單一元素處理循環(huán)

@ 處理向量循環(huán)

vectors:

subs r3, r3, #1 @減少循環(huán)計數器個(gè)數

vld1.8 {d0}, [r0]! @ 從數組加載8個(gè)元素,從地址r0到寄存器d0,然后更新地址寄存器r0到下一個(gè)向量地址;

...

... @ 處理在d0寄存器的數據

...

vst1.8 {d0}, [r1]! @ 把8個(gè)結果元素保存到輸出數組,更新地址r1到下一個(gè)向量

bne vectors @如果r3不等于0,繼續循環(huán)

singlesetup:

ands r3, r2, #7 @ 計算單一元素迭代的次數

beq exit @ 如果單一元素計算次數為0,則跳轉退出

@ 處理單一元素的循環(huán)

singles:

subs r3, r3, #1 @減少循環(huán)計數器個(gè)數

vld1.8 {d0[0]}, [r0]! @從數組加載單一元素,從地址r0到寄存器d0,然后更新地址寄存器r0到下一個(gè)地址

...

... @ 處理在d0[0]內的輸入數據

...

vst1.8 {d0[0]}, [r1]! @ 保存單一元素結果到輸出數組,更新指針地址

bne singles @如果r3不等于0,繼續循環(huán)

exit:

其他的考慮

在開(kāi)始處還是結束處

用重疊計算的方式以及用單一元素處理都能在數組開(kāi)始處或者結束處處理,因而代碼就要考慮兩種實(shí)現方式哪種效率高些,哪個(gè)更適合你的系統應用。

數據對齊

加載或者存儲指令的地址應該對齊到cache line,這樣內存的訪(fǎng)問(wèn)效率更高。這樣就需要在Cortex-A8的處理器上至少16字對齊,如果你不能把輸入和輸出數組的起始地址對齊到16字,你就必須處理開(kāi)始和結束數據處理的那若干個(gè)元素以使得后續的數據訪(fǎng)問(wèn)是對齊到cache行的。為了使用內存對齊的方式訪(fǎng)問(wèn)內存以提高速度,你在使用NEON指令時(shí)需要使用諸如64或者128或者256等地址限定符來(lái)制定加載和存儲指令。你可以比較發(fā)出一個(gè)對齊的訪(fǎng)問(wèn)和非對齊訪(fǎng)問(wèn)的性能,以下是始終周期的頁(yè)面Cortex-A8 TRM.

使用ARM來(lái)做修復

在使用單個(gè)元素處理的情況下,你可以使用ARM指令來(lái)進(jìn)行單個(gè)元素的操作,但是同時(shí)使用ARM和NEON來(lái)訪(fǎng)問(wèn)同一塊區域的內存會(huì )降低系統性能,因為從ARM的流水線(xiàn)發(fā)出的寫(xiě)操作會(huì )在NEON的流水線(xiàn)完成之后才能進(jìn)行。因而你要盡量的避免在A(yíng)RM和NEON的代碼里同時(shí)訪(fǎng)問(wèn)同一塊內存區域(當然,這同一塊內存區域也對應于同一個(gè)cache line)



評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>