在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

NEON編程中的一些常見優化技巧

安芯教育科技 ? 來源:安謀科技學堂 ? 作者:安謀科技學堂 ? 2022-12-12 09:11 ? 次閱讀

1.簡介

讀過上一篇文章“ARM NEON快速上手指南”之后,相信你已經對ARM NEON編程有了基本的認識。但在真正利用ARM NEON優化程序性能時,還有很多編程技巧和注意事項。本文將結合本人的一些開發經歷,介紹NEON編程中的一些常見優化技巧,希望能對用戶在NEON實際開發中有些借鑒意義。

2.NEON優化技術

在利用NEON優化程序時,有下述幾項比較通用的優化技巧。

2.1 降低數據依賴性

在ARM v7-A NEON指令通常需要3~9個指令周期,NEON指令比ARM指令需要更多周期數。因此,為了減少指令延時,最好避免將當前指令的目的寄存器當作下條指令的源寄存器。如下例所示:

// C代碼
float SumSquareError_C(const float* src_a, const float* src_b, int count) 
{
  float sse = 0u;
  int i;
  for (i = 0; i < count; ++i) {
    float diff = src_a[i] - src_b[i];
    sse += (float)(diff * diff);
  }
  return sse;
}
// NEON實現一
float SumSquareError_NEON1(const float* src_a, const float* src_b, int count)
{
  float sse;
  asm volatile (
    "veor    q8, q8, q8                        
"
    "veor    q9, q9, q9                        
"
    "veor    q10, q10, q10                     
"
    "veor    q11, q11, q11                     
"

  "1:                                          
"
    "vld1.32     {q0, q1}, [%0]!               
"
    "vld1.32     {q2, q3}, [%0]!               
"
    "vld1.32     {q12, q13}, [%1]!             
"
    "vld1.32     {q14, q15}, [%1]!             
"
    "subs       %2, %2, #16                    
"
    // q0, q1, q2, q3 是vsub的目的地寄存器.
    // 也是vmla的源寄存器。
    "vsub.f32   q0, q0, q12                    
"
    "vmla.f32   q8, q0, q0                     
"

    "vsub.f32   q1, q1, q13                    
"
    "vmla.f32   q9, q1, q1                     
"

    "vsub.f32   q2, q2, q14                    
"
    "vmla.f32   q10, q2, q2                    
"

    "vsub.f32   q3, q3, q15                    
"
    "vmla.f32   q11, q3, q3                    
"
    "bgt        1b                             
"

    "vadd.f32   q8, q8, q9                     
"
    "vadd.f32   q10, q10, q11                  
"
    "vadd.f32   q11, q8, q10                   
"
    "vpadd.f32  d2, d22, d23                   
"
    "vpadd.f32  d0, d2, d2                     
"
    "vmov.32    %3, d0[0]                      
"
    : "+r"(src_a),
      "+r"(src_b),
      "+r"(count),
      "=r"(sse)
    :
    : "memory", "cc", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11","q12", "q13","q14", "q15");
  return sse;
}
// NEON實現二
float SumSquareError_NEON2(const float* src_a, const float* src_b, int count)
{
  float sse;
  asm volatile (
    "veor    q8, q8, q8                        
"
    "veor    q9, q9, q9                        
"
    "veor    q10, q10, q10                     
"
    "veor    q11, q11, q11                     
"

  "1:                                          
"
    "vld1.32     {q0, q1}, [%0]!               
"
    "vld1.32     {q2, q3}, [%0]!               
"
    "vld1.32     {q12, q13}, [%1]!             
"
    "vld1.32     {q14, q15}, [%1]!             
"
    "subs       %2, %2, #16                    
"
    "vsub.f32   q0, q0, q12                    
"
    "vsub.f32   q1, q1, q13                    
"
    "vsub.f32   q2, q2, q14                    
"
    "vsub.f32   q3, q3, q15                    
"
    
    "vmla.f32   q8, q0, q0                     
"
    "vmla.f32   q9, q1, q1                     
"
    "vmla.f32   q10, q2, q2                    
"
    "vmla.f32   q11, q3, q3                    
"
    "bgt        1b                             
"

    "vadd.f32   q8, q8, q9                     
"
    "vadd.f32   q10, q10, q11                  
"
    "vadd.f32   q11, q8, q10                   
"
    "vpadd.f32  d2, d22, d23                   
"
    "vpadd.f32  d0, d2, d2                     
"
    "vmov.32    %3, d0[0]                      
"
    : "+r"(src_a),
      "+r"(src_b),
      "+r"(count),
      "=r"(sse)
    :
    : "memory", "cc", "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13","q14", "q15");
  return sse;
}

在NEON實現一中,我們把目的寄存器立刻當作源寄存器;在NEON實現二中,我們重新排布了指令,并給予目的寄存器盡量多的延時。經過測試實現二比實現一快30%。由此可見,降低數據依賴性對于提高程序性能有重要意義。一個好消息是編譯器能自動調整NEON intrinsics以降低數據依賴性。這個利用NEON intrinsics的一個很大優勢。

2.2 減少跳轉

NEON指令集沒有跳轉指令,當需要跳轉時,我們需要借助ARM指令。在ARM處理器中,分支預測技術被廣泛使用。但是一旦分支預測失敗,懲罰還是比較高的。因此我們最好盡量減少跳轉指令的使用。其實,在有些情況下,我們可以用邏輯運算來代替跳轉,如下例所示:

// C實現
if( flag )
{
        dst[x * 4]     = a;
        dst[x * 4 + 1] = a;
        dst[x * 4 + 2] = a;
        dst[x * 4 + 3] = a;
}
else
{
        dst[x * 4]     = b;
        dst[x * 4 + 1] = b;
        dst[x * 4 + 2] = b;
        dst[x * 4 + 3] = b;
}
// NEON實現
//dst[x * 4]     = (a&Eflag) | (b&~Eflag);
//dst[x * 4 + 1] = (a&Eflag) | (b&~Eflag);
//dst[x * 4 + 2] = (a&Eflag) | (b&~Eflag);
//dst[x * 4 + 3] = (a&Eflag) | (b&~Eflag);

VBSL qFlag, qA, qB

ARM NEON指令集提供了下列指令來幫助用戶實現上述邏輯實現:

? VCEQ, VCGE, VCGT, VCLE, VCLT……

? VBIT, VBIF, VBSL……

減少跳轉,不僅僅是在NEON中使用的技巧,是一個比較通用的問題。即使在C程序中,這個問題也是值得注意的。

2.3 其它技巧

在ARM NEON編程時,一種功能有時有多種實現方式,但是更少的指令不總是意味著更好的性能,要依據測試結果和profiling數據,具體問題具體分析。下面列出來我遇到的一些特殊情況。2.3.1 浮點累加指令通常情況下,我們會用VMLA/VMLS來代替VMUL + VADD/ VMUL + VSUB,這樣使用較少的指令,完成更多的功能。但是與浮點VMUL相比,浮點VMLA/VMLS具有更長的指令延時,如果在指令延時中間不能插入其它計算的情況下,使用浮點VMUL + VADD/ VMUL + VSUB反而具有更好的性能。一個真實例子就是Ne10庫函數的浮點FIR函數。代碼片段如下所示:

實現1:在兩條VMLA指令之間,僅有VEXT指令。而根據指令延時表,VMLA需要9個周期。

實現2:對于qAcc0,依然存在指令延時。但是VADD/VMUL只需要5個周期。下列代碼中周期n粗略地表示了指令執行需要的周期數。與實現1相比,實現2節省了6個周期。性能測試也表明實現2具有更好的性能。

實現 1: VMLA
VEXT qTemp1,qInp,qTemp,#1
VMLA qAcc0,qInp,dCoeff_0[0]-- cycle 0

VEXT qTemp2,qInp,qTemp,#2
VMLA qAcc0,qTemp1,dCoeff_0[1] -- cycle 9

VEXT qTemp3,qInp,qTemp,#3
VMLA qAcc0,qTemp2,dCoeff_1[0] -- cycle 18

VMLA qAcc0,qTemp3,dCoeff_1[1] -- cycle 27
得到最終結果 qAcc0需要36個指令周期。
實現 2:  VMUL+VADD
VEXT qTemp1,qInp,qTemp,#1
VMLA qAcc0,qInp,dCoeff_0[0] ]-- cycle 0
VMUL qAcc1,qTemp1,dCoeff_0[1]

VEXT qTemp2,qInp,qTemp,#2
VMUL qAcc2,qTemp2,dCoeff_1[0]
VADD qAcc0, qAcc0, qAcc1-- cycle 9

VEXT qTemp3,qInp,qTemp,#3
VMUL qAcc3,qTemp3,dCoeff_1[1]
VADD qAcc0, qAcc0, qAcc2-- cycle 14 

VADD qAcc0, qAcc0, qAcc3-- cycle 19
得到最終結果 qAcc0需要24個指令周期。
與實現1相比,三條VADD指令需要6個發射指令周期。總共需要 30個指令周期。

modules/dsp/NE10_fir.neon.s:line 195

指令延時請參考下表:

Name Format Cycles Result
VADD/VSUB/VMUL Qd,Qn,Dm 2 5
VMLA/VMLS Qd,Qn,Dm 2 9

表格來源于Cortex-A9 NEON Media Processing Engine Revision: r4p1 Technical Reference Manual: 3.4.8。

表格中:? Cycles:指令發射時間

? Result:指令執行時間

2.4 小結

總結起來,NEON的優化技巧主要有以下幾點

? 盡量利用指令執行延時,合理安排指令順序

? 少用跳轉

? 注意cache命中率

審核編輯:郭婷


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • ARM
    ARM
    +關注

    關注

    134

    文章

    9328

    瀏覽量

    375680
  • 寄存器
    +關注

    關注

    31

    文章

    5427

    瀏覽量

    123714

原文標題:Arm NEON學習(二)優化技術

文章出處:【微信號:Ithingedu,微信公眾號:安芯教育科技】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    Debian和Ubuntu哪個好一些

    兼容性對比Debian和Ubuntu哪個好一些,并為您揭示如何通過RAKsmart服務器釋放Linux系統的最大潛能。
    的頭像 發表于 05-07 10:58 ?266次閱讀

    樹莓派在自動化控制項目中的一些潛在應用

    自動化控制項目中的一些潛在應用。之前,我們已經為Arduino平臺探討了相同的話題。我們確定Arduino是個出色的教育工具,但由于一些限制,它無法在工業環境完全
    的頭像 發表于 03-25 09:45 ?176次閱讀
    樹莓派在自動化控制項目中的<b class='flag-5'>一些</b>潛在應用

    嵌入式系統的代碼優化與壓縮技術

    不是繼續遍歷整個數組。 函數調用優化:頻繁的函數調用會帶來額外的開銷,包括參數傳遞、棧操作等。對于一些短小且頻繁調用的函數,可以將其定義為內聯函數,這樣在編譯時,函數代碼會直接嵌入到調用處,減少函數
    發表于 02-26 15:00

    Littrow結構光柵系統的配置與優化

    的Littrow配置 我們在這里提供了個根據Littrow配置的光學裝置,而且通過一些編程,即使在波長或光柵周期的變化下,也能保持光柵的最佳位置。 高效偏振無關傳輸光柵的分析與設計 我們演示了如何嚴格分析二元光柵的偏振相關
    發表于 12-25 15:35

    EEPROM編程常見錯誤及解決方案

    EEPROM(電可擦可編程只讀存儲器)在編程過程可能會遇到多種錯誤。以下是一些常見的EEPROM編程
    的頭像 發表于 12-16 17:08 ?4199次閱讀

    串聯電容的常見應用 如何優化串聯電路的效率

    串聯電容的常見應用 串聯電容是常見的電路元件連接方式,其在家居、工業及電力系統等多個領域有著廣泛的應用。以下是串聯電容的一些常見應用:
    的頭像 發表于 12-02 16:35 ?3832次閱讀

    一些常見的動態電路

    無論是模電還是數電,理論知識相對來說還是比較枯燥,各種電路原理理解清楚不算容易,換種生動形象的方式或許會增加一些趣味性,也更容易理解這些知識。下面整理了一些常見的電路,以動態圖形的方
    的頭像 發表于 11-16 09:26 ?1014次閱讀
    <b class='flag-5'>一些</b><b class='flag-5'>常見</b>的動態電路

    編程語言的誤區與常見問題

    誤區編程語言的選擇 常見問題: 初學者在選擇編程語言時,往往會被市場上的熱門語言所吸引,而忽視了自己的實際需求和興趣。 一些開發者認為某
    的頭像 發表于 11-15 09:35 ?691次閱讀

    分享一些常見的電路

    理解模電和數電的電路原理對于初學者來說可能比較困難,但通過一些生動的教學方法和資源,可以有效地提高學習興趣和理解能力。 下面整理了一些常見的電路,以動態圖形的方式展示。 整流電路 單相橋式整流
    的頭像 發表于 11-13 09:28 ?765次閱讀
    分享<b class='flag-5'>一些</b><b class='flag-5'>常見</b>的電路

    ASCII碼在編程的應用實例

    ASCII碼(American Standard Code for Information Interchange,美國信息交換標準代碼)在編程中有著廣泛的應用。以下是一些ASCII碼在編程
    的頭像 發表于 11-10 09:43 ?1394次閱讀

    MySQL性能優化淺析及線上案例

    作者:京東健康 孟飛 1、 數據庫性能優化的意義 業務發展初期,數據庫中量般都不高,也不太容易出一些性能問題或者出的問題也不大,但是當數據庫的量級達到定規模之后,如果缺失有效的預警
    的頭像 發表于 10-22 15:17 ?985次閱讀
    MySQL性能<b class='flag-5'>優化</b>淺析及線上案例

    LED驅動器應用的一些指南和技巧

    電子發燒友網站提供《LED驅動器應用的一些指南和技巧.pdf》資料免費下載
    發表于 09-25 11:35 ?0次下載
    LED驅動器應用的<b class='flag-5'>一些</b>指南和技巧

    關于一些有助于優化電源設計的新型材料

    眾所周知,人們對更高電源效率的追求正在推動性能的全方位提升。材料科學的進步對于優化電源設計和開發更高效、更緊湊和更可靠的解決方案發揮著關鍵作用。下文列出了一些有助于優化電源設計的新材料。
    的頭像 發表于 08-29 15:26 ?716次閱讀

    二進制處理一些技巧

    在二進制和十進制的處理,有時候一些小技巧是很有用的。 1、把十進制數轉換成二進制數 (1)在MATLAB中有個函數dec2bin,可以把正整數轉換為2進制 (2)對于負數有這樣
    的頭像 發表于 07-05 11:51 ?915次閱讀

    聚徽觸控 - 教學體機常見故障及解決辦法

    教學體機在使用過程可能會遇到多種故障,以下是一些常見的故障及解決辦法:
    的頭像 發表于 07-01 15:44 ?1419次閱讀
    主站蜘蛛池模板: 日本黄色美女网站 | 国产亚洲综合精品一区二区三区 | 国产精品免费观看网站 | 高h污快穿文汁水四溅 | 国产女人和拘做受视频免费 | 欧美一级欧美三级在线 | 99久久99这里只有免费费精品 | 久久夜夜操 | 男男全肉高h腐文 | 狠狠操亚洲 | 国产精品免费看久久久久 | 丝袜美腿视频一区二区三区 | 亚洲精品第三页 | 欧美3d成人动画在线 | 国产三级日本三级韩国三级在线观看 | 欧美一区二区三区成人看不卡 | 日本在线不卡一区二区 | 日韩电影毛片 | 欧美一区二区三区男人的天堂 | 日本19xxxxxxxxx69 日本68xxxxxxxxx59 | 亚洲三级在线免费观看 | 日韩一卡 二卡 三卡 四卡 免费视频 | 婷婷午夜 | 久久久久久久久综合 | 亚洲综合色视频 | 日本片巨大的乳456线观看 | 国产1卡2卡三卡四卡网站 | 久久99国产亚洲高清观看首页 | 最近2018中文字幕免费看手机 | 四虎影院在线观看网站 | 天天做天天爱夜夜爽 | 欧美四虎影院 | 欧美 日韩 中文字幕 | 激情综合亚洲 | 亚洲高清中文字幕一区二区三区 | 国产精品久久久久久久久久免费 | 日本一区二区三区欧美在线观看 | 又黄又视频 | 欧美一级看片免费观看视频在线 | 午夜黄页网站在线播放 | 四虎在线视频 |