新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > ARM處理器NEON編程及優(yōu)化技巧——數(shù)據(jù)加載和存儲

        ARM處理器NEON編程及優(yōu)化技巧——數(shù)據(jù)加載和存儲

        作者: 時間:2016-11-10 來源:網絡 收藏
        ARM的NEON協(xié)處理器技術是一個64/128-bit的混合SIMD架構,用于加速包括視頻編碼解碼、音頻解碼編碼、3D圖像、語音和圖像等多媒體和信號處理應用。本文主要介紹如何使用NEON的匯編程序來寫SIMD的代碼,包括如何開始NEON的開發(fā),如何高效的利用NEON。首先會關注內存操作,即如何變更指令來靈活有效的加載和存儲數(shù)據(jù)。接下來是由于SIMD指令的應用而導致剩下的若干個單元的處理,最后是一個例子來說明用NEON來進行SIMD優(yōu)化。

        SIMD的例子

        本文引用地址:http://www.104case.com/article/201611/317427.htm

        首先看一個實例,24-bit的RGB圖像,像素在內存里的組織方式是R, G, B, R, G, B...,如果你想做一個簡單的圖像處理,比如把R和B通道互換,你該如何高效的使用NEON協(xié)處理器呢?首先從存儲空間線性加載RGB數(shù)據(jù)到D寄存器,然后交換R和B數(shù)據(jù)。 但是這種線性加載的數(shù)據(jù)進行R和B通道的數(shù)據(jù)交換非常麻煩,需要首先掩碼mask,然后移位并合并掩碼數(shù)據(jù)。這種復雜的運算顯然并不高效。

        圖1. 線性加載RGB數(shù)據(jù)

        NEON提供了各種結構的加載和存儲指令來處理這種情況,這些指令能把數(shù)據(jù)從存儲區(qū)加載的同時還能把這些值分開存儲到不同的寄存器中,如下圖2所示,你可以使用VLD3加載來把RGB數(shù)據(jù)分開存儲。

        圖2. 使用結構化的加載指令加載RGB數(shù)據(jù)

        然后使用VLD3分開加載的數(shù)據(jù)就能方便的使用指令(VSWP d0, d2)來進行R和B通道的交換了,然后把結果再寫入內存,當然也要使用interleave交織模式的存儲,即VST3存儲指令。

        圖3. 交換寄存器d0和d2然后存儲

        結構化加載和存儲語法和具體指令

        NEON結構化加載會讀取內存內容到64-bit的NEON寄存器,使用可選的deinterleave選項,同樣加載指令也可以采用這種reinterleave的方式把寄存器的內容寫到內存空間。

        圖4. NEON的結構化加載和存儲

        下面介紹NEON存儲和加載的結構化方式,語法包括如下5個部分:

        圖5. NEON的結構化加載和存儲語法

        • 加載VLD或者存儲VST指令助記符:instruction mnemonic
        • 一個表示interleave模式的數(shù)字,表示每個結構體元素間的間隔:interleave pattern
        • 表示每次訪問單元的位寬比特數(shù),即結構體內元素類型:element type
        • 讀寫的64-bit的NEON寄存器集合,最多可以列出4個寄存器,取決于interleave模式:NEON registers
        • 表示內存訪問地址的ARM寄存器,該地址可以在每次訪問時更新: ARMaddress register

        交織模式:Interleave Pattern

        加載和存儲指令可以用從1到4個相同大小的元素的交織結構體,這些元素可以是NEON指令通常支持的8,16或者32比特。

        • VLD1是最簡單的形式,從內存加載1~4個寄存器的數(shù)據(jù),沒有deinterleave,即線性加載;
        • VLD2加載2或者4個寄存器的數(shù)據(jù),解交織奇偶元素到各自的寄存器,這樣很容易的把交織的立體聲音頻數(shù)據(jù)分解為左右聲道的數(shù)據(jù);
        • VLD3加載3個寄存器的數(shù)據(jù),很方便的把RGB的數(shù)據(jù)分為R、G、B通道;
        • VLD4加載4個寄存器的數(shù)據(jù),解交織,用于分解ARGB圖像數(shù)據(jù);

        存儲和加載類似,只是把寄存器的數(shù)據(jù)interleave然后寫到內存。

        元素類型Element Types

        加載和存儲interleave的數(shù)據(jù)的基本元素可以為8,16或者32比特的數(shù)據(jù)。比如NEON指令VLD2.16將加載4個16-bit元素到第一個寄存器,然后4個16-bit元素到第二個寄存器,把臨近的奇偶對分開保存到每個寄存器。

        圖6. 加載并解交織16-bit的數(shù)據(jù)

        把元素大小變成32-bits還是加載相同大小的數(shù)據(jù),但是只有2個元素來構成一個向量,同樣分成奇偶元素部分。

        圖6. 加載并解交織32-bit的數(shù)據(jù)

        元素大小還會影響大小端的處理。如果你指定了正確的加載和存儲指令的元素大小,從存儲空間讀取和存儲的字節(jié)都會按照正確的次序排列,因而相同的代碼會在大端和小端系統(tǒng)里適用。最后元素大小還會影響指針的數(shù)據(jù)對齊,把數(shù)據(jù)對齊到元素大小的邊界能帶來更好的性能,當然這也是一般的操作系統(tǒng)OS要求的。如,加載32位元素數(shù)據(jù),通常要把第一個元素的地址對齊到32位邊界。

        單個或者多個元素 Single or Multiple Elements

        除了加載多個元素,結構讀取還能從內存用deinterleave的模式讀取一個元素到NEON寄存器的多個通道或者一個通道而保存其他通道不變。

        圖7. 加載并解交織到所有的通道

        加載到單一通道對于從分散的內存空間的數(shù)據(jù)讀取來構建一個向量非常有用。存儲數(shù)據(jù)到內存也是一樣,也可以采用通道的模式進行存儲。

        圖7. 加載并解交織到單一的通道

        尋址模式Addressing

        NEON的加載和存儲指令支持3種格式的尋址模式:

        • 寄存器 [ {,:}]:數(shù)據(jù)將會從指定寄存器的地址加載或者存儲;
        • 帶自動加減地址更新的寄存器[{,:}]!:在數(shù)據(jù)從指定寄存器的地址加載或者存儲后會更新地址,更新的地址大小等于讀取或者存儲的數(shù)據(jù)元素大??;
        • 帶后索引的寄存器[{,:}],:存儲空間訪問后,會根據(jù)制定的寄存器Rm來更新地址,當需要讀取或者存儲一組具有固定間隔的數(shù)據(jù)時非常有用。

        其他的加載和存儲

        NEON還支持以下的數(shù)據(jù)加載和存儲:

        • VLDR和VSTR來加載和存儲64-bit數(shù)值到一個單一的寄存器;
        • VLDM和VSTM來從堆棧加載或者存儲多個64-bit數(shù)值;

        更多的關于支持的加載和存儲運算可以參考ARM的參考手冊arm.com/help/index.jsp?topic=/com.arm.doc.ddi0406b/index.html" rel="nofollow">ARM Architecture Reference Manual. 詳細的指令周期信息可以參考每個單獨的指令Technical Reference Manual for each core.



        評論


        技術專區(qū)

        關閉
        主站蜘蛛池模板: 绥化市| 瓦房店市| 乐安县| 香港| 法库县| 当阳市| 奈曼旗| 濮阳县| 青海省| 溧阳市| 铜梁县| 自贡市| 甘南县| 娄底市| 若尔盖县| 平阳县| 永兴县| 鲁甸县| 克拉玛依市| 道孚县| 金堂县| 沙洋县| 宣城市| 潜山县| 永丰县| 娱乐| 平利县| 甘孜县| 白城市| 关岭| 马龙县| 定远县| 额敏县| 陆丰市| 固原市| 枣庄市| 玛沁县| 长垣县| 隆昌县| 丹阳市| 桐柏县|