chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

NEON編程中的一些常見優(yōu)化技巧

安芯教育科技 ? 來源:安謀科技學(xué)堂 ? 作者:安謀科技學(xué)堂 ? 2022-12-12 09:11 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1.簡介

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

2.NEON優(yōu)化技術(shù)

在利用NEON優(yōu)化程序時(shí),有下述幾項(xiàng)比較通用的優(yōu)化技巧。

2.1 降低數(shù)據(jù)依賴性

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

// 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實(shí)現(xiàn)一
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實(shí)現(xiàn)二
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實(shí)現(xiàn)一中,我們把目的寄存器立刻當(dāng)作源寄存器;在NEON實(shí)現(xiàn)二中,我們重新排布了指令,并給予目的寄存器盡量多的延時(shí)。經(jīng)過測試實(shí)現(xiàn)二比實(shí)現(xiàn)一快30%。由此可見,降低數(shù)據(jù)依賴性對于提高程序性能有重要意義。一個(gè)好消息是編譯器能自動調(diào)整NEON intrinsics以降低數(shù)據(jù)依賴性。這個(gè)利用NEON intrinsics的一個(gè)很大優(yōu)勢。

2.2 減少跳轉(zhuǎn)

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

// C實(shí)現(xiàn)
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實(shí)現(xiàn)
//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指令集提供了下列指令來幫助用戶實(shí)現(xiàn)上述邏輯實(shí)現(xiàn):

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

? VBIT, VBIF, VBSL……

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

2.3 其它技巧

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

實(shí)現(xiàn)1:在兩條VMLA指令之間,僅有VEXT指令。而根據(jù)指令延時(shí)表,VMLA需要9個(gè)周期。

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

實(shí)現(xiàn) 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
得到最終結(jié)果 qAcc0需要36個(gè)指令周期。
實(shí)現(xiàn) 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
得到最終結(jié)果 qAcc0需要24個(gè)指令周期。
與實(shí)現(xiàn)1相比,三條VADD指令需要6個(gè)發(fā)射指令周期??偣残枰?30個(gè)指令周期。

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

指令延時(shí)請參考下表:

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:指令發(fā)射時(shí)間

? Result:指令執(zhí)行時(shí)間

2.4 小結(jié)

總結(jié)起來,NEON的優(yōu)化技巧主要有以下幾點(diǎn)

? 盡量利用指令執(zhí)行延時(shí),合理安排指令順序

? 少用跳轉(zhuǎn)

? 注意cache命中率

審核編輯:郭婷


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    135

    文章

    9582

    瀏覽量

    393456
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5617

    瀏覽量

    130378

原文標(biāo)題:Arm NEON學(xué)習(xí)(二)優(yōu)化技術(shù)

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

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    如何使用 powerquad 加速器一些功能以及 CMSIS 原始實(shí)現(xiàn)一些功能?

    )。 如何使用 powerquad 加速器一些功能以及 CMSIS 原始實(shí)現(xiàn)一些功能。 Example: I do not want to call arm_mat_tran
    發(fā)表于 04-03 06:37

    變頻器應(yīng)用的一些技巧

    變頻器作為現(xiàn)代工業(yè)控制的核心設(shè)備,其應(yīng)用范圍已從傳統(tǒng)的電機(jī)調(diào)速擴(kuò)展到節(jié)能改造、自動化生產(chǎn)線、新能源等領(lǐng)域。隨著技術(shù)的迭代,如何充分發(fā)揮變頻器性能并規(guī)避常見問題,成為工程師關(guān)注的焦點(diǎn)。以下從選型配置、參數(shù)調(diào)試、故障排查等維度,結(jié)合行業(yè)實(shí)踐案例,系統(tǒng)梳理變頻器的應(yīng)用技巧。
    的頭像 發(fā)表于 03-25 16:31 ?165次閱讀

    爬壁機(jī)器人磁鐵的一些常見問題

    爬壁機(jī)器人近幾年比較火,它是類能夠在垂直墻面、天花板、傾斜表面上移動和作業(yè)的特種機(jī)器人,今天我們不聊其它,只聊下關(guān)于磁吸附應(yīng)用的磁鐵,以下是小編整理的關(guān)于爬壁機(jī)器人中磁鐵的一些常見
    的頭像 發(fā)表于 01-09 10:06 ?395次閱讀
    爬壁機(jī)器人磁鐵的<b class='flag-5'>一些</b><b class='flag-5'>常見</b>問題

    CW32系統(tǒng)有哪些常見問題?

    在CW32系統(tǒng),可能會遇到一些常見問題,包括但不限于: 重復(fù)定義函數(shù):例如在a.c里定義了函數(shù)void func(),在b.c里也定義了個(gè)void func()。這會導(dǎo)致編譯時(shí)出
    發(fā)表于 12-15 06:47

    關(guān)于六類網(wǎng)線一些問題的解答

    今天我們就圍繞網(wǎng)友一些常見的關(guān)于六類網(wǎng)線的問題進(jìn)行下匯總式解答: 問 六類網(wǎng)線可以當(dāng)電源用嗎? 答 六類網(wǎng)線并不是設(shè)計(jì)用于傳輸電力的電纜,因此般不建議將其用于電源傳輸。 盡管六類網(wǎng)
    的頭像 發(fā)表于 12-09 11:13 ?737次閱讀

    貼片電容精度J±5%的一些詳細(xì)知識

    貼片電容精度J±5%表示電容的實(shí)際值與標(biāo)稱值之間的偏差范圍在±5%以內(nèi) ,以下是關(guān)于貼片電容精度J±5%的一些詳細(xì)知識: 、精度等級含義 J±5% :字母“J”在貼片電容的標(biāo)識通常表示標(biāo)稱精度
    的頭像 發(fā)表于 11-20 14:38 ?928次閱讀
    貼片電容精度J±5%的<b class='flag-5'>一些</b>詳細(xì)知識

    對浮點(diǎn)指令擴(kuò)展中一些問題的解決與分享

    出現(xiàn)無法寫的情況。 結(jié)論 以上就是我們組在擴(kuò)展浮點(diǎn)指令中出現(xiàn)的一些問題,這些問題總體上歸結(jié)于對蜂鳥的代碼沒有整體性的把握,對內(nèi)容的掌握程度還不夠。在后續(xù)的工作應(yīng)注意理清功能的整體架構(gòu)而對所有的相關(guān)部分進(jìn)行修改。
    發(fā)表于 10-24 11:47

    蜂鳥E203的浮點(diǎn)指令集F的一些實(shí)現(xiàn)細(xì)節(jié)

    周期。 總結(jié) 本文介紹的內(nèi)容是為了完成基礎(chǔ)功能:對蜂鳥E203 RISC-V內(nèi)核的微架構(gòu)實(shí)現(xiàn)進(jìn)行優(yōu)化,在添加F拓展的過程一些記錄。
    發(fā)表于 10-24 08:57

    Vivado浮點(diǎn)數(shù)IP核的一些設(shè)置注意點(diǎn)

    : 總結(jié) 本文介紹的內(nèi)容是為了完成基礎(chǔ)功能:對蜂鳥E203 RISC-V內(nèi)核的微架構(gòu)實(shí)現(xiàn)進(jìn)行優(yōu)化,在添加F拓展的過程一些記錄。
    發(fā)表于 10-24 06:25

    在Ubuntu20.04系統(tǒng)訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型的一些經(jīng)驗(yàn)

    本帖欲分享在Ubuntu20.04系統(tǒng)訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型的一些經(jīng)驗(yàn)。我們采用jupyter notebook作為開發(fā)IDE,以TensorFlow2為訓(xùn)練框架,目標(biāo)是訓(xùn)練個(gè)手寫數(shù)字識別的神經(jīng)網(wǎng)絡(luò)
    發(fā)表于 10-22 07:03

    射頻工程師需要知道的一些常見轉(zhuǎn)接頭

    ,是由于轉(zhuǎn)接頭的損壞造成的,而且有些接頭的連接固定的方式不對,每次修好的儀器,過去后客戶又按照他們原來的方式去擰緊了。特別是在一些生產(chǎn)型的企業(yè),由于操作人員流動性比較
    的頭像 發(fā)表于 08-06 17:39 ?1498次閱讀
    射頻工程師需要知道的<b class='flag-5'>一些</b><b class='flag-5'>常見</b>轉(zhuǎn)接頭

    如何優(yōu)化編程電源控制環(huán)路參數(shù)?

    時(shí)環(huán)路相位裕度僅25°,輸出電壓振蕩(頻率10kHz)。 優(yōu)化措施:在補(bǔ)償網(wǎng)絡(luò)增加個(gè)小電容(10pF),引入個(gè)高頻極點(diǎn)衰減振蕩;調(diào)整補(bǔ)償電容CCOMP?從10nF增至22nF,提
    發(fā)表于 07-02 15:56

    在低功耗藍(lán)牙產(chǎn)品開發(fā)的過程,會涉及到一些參數(shù)的選擇和設(shè)定,這些參數(shù)是什么意思,該如何設(shè)定呢?(藍(lán)牙廣播)

    在低功耗藍(lán)牙產(chǎn)品開發(fā)的過程,會涉及到一些參數(shù)的選擇和設(shè)定,這些參數(shù)是什么意思,該如何設(shè)定呢?在此介紹一些: 藍(lán)牙的廣播類型(Advertising Type) 可連接廣播(ADV_IND):允許
    發(fā)表于 06-25 18:25

    HarmonyOS優(yōu)化應(yīng)用內(nèi)存占用問題性能優(yōu)化

    應(yīng)用開發(fā)過程中注重內(nèi)存管理,積極采取措施來減少內(nèi)存占用,以優(yōu)化應(yīng)用程序的性能和用戶體驗(yàn)。 HarmonyOS提供了一些內(nèi)存管理的工具和接口,幫助開發(fā)者有效地管理內(nèi)存資源: onMemoryLevel接口
    發(fā)表于 05-21 11:27

    Debian和Ubuntu哪個(gè)好一些?

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