新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 在Cortex-A8平臺(tái)下memcpy ARM/NEON匯編性能的測試

在Cortex-A8平臺(tái)下memcpy ARM/NEON匯編性能的測試

作者: 時(shí)間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
本文介紹了基于ARMv7架構(gòu)的Cortex-A8芯片(FreeScale i.MX51 / i.MX53/QualComm msm8x50 / msm7x30/Samsung s5pc100 / s5pc110/TI omap 3430 / omap 3730芯片)上采用C語言、ARM匯編和NEON匯編實(shí)現(xiàn)的memcpy的性能對比,并輸入分析了NEON指令(不同處理器的NEON內(nèi)存位寬從64-bit到128-bit不等)和cache的預(yù)取preload(preload engine指令)對性能的影響。最終結(jié)論表明1.在拷貝塊大小block size = 512B ~ 32K之間,有一個(gè)性能高臺(tái),block size = 256K也有一個(gè)性能的轉(zhuǎn)折。這個(gè)特性體現(xiàn)了芯片32KB L1 / 256KB L2 cache的影響;2. NEON指令的性能總是要高于ARM指令的性能。隨著發(fā)展ARM/NEON指令之間性能差在縮小。交替使用ARM/NEON指令,性能往往要差于NEON版本;3.如果沒有很好的模型設(shè)計(jì),軟件去干預(yù)cache的使用,很容易會(huì)造成性能的惡化; 4.在fit in cache條件下,Snapdragon平臺(tái)有最好的性能; 5.在out of cache條件下,s5pc110有最好的性能; 6.在同一個(gè)硬件平臺(tái)下,超頻對memory性能影響很小; 7.同一種的實(shí)現(xiàn),在不同的硬件平臺(tái)上都有不同的表現(xiàn)。沒有一種實(shí)現(xiàn)在所有平臺(tái)上是最好的。
  1. 前言

    在C run time library中,memcpy是重要的函數(shù),對應(yīng)用軟件的性能有著重要的影響。ARM芯片發(fā)展到Cortex-A8[1][2]架構(gòu),不但頻率有了很大提升,而且架構(gòu)設(shè)計(jì)有了很大地改進(jìn)。其中增加的NEON指令,是類似于原先X86平臺(tái)下的MMX指令,是為多媒體而設(shè)計(jì)。但因?yàn)檫@類指令一次可以處理64-bit數(shù)據(jù),對memcpy函數(shù)性能提升也很有幫助。本文主要是測試采用NEON[2]指令的多種memcpy實(shí)現(xiàn),探討NEON指令和預(yù)取(preload)指令對性能的影響,以及在芯片優(yōu)化和工藝進(jìn)步后,這些影響的變化趨勢。同時(shí)希望芯片設(shè)計(jì)人員在了解軟件實(shí)現(xiàn)的基礎(chǔ)上,給予一個(gè)知其然,也知其所以然的解釋,進(jìn)而指導(dǎo)進(jìn)一步提高性能的方向。

    本文引用地址:http://butianyuan.cn/article/201611/317414.htm
  2. 平臺(tái)介紹

    本次的測試平臺(tái)來源于筆者工作項(xiàng)目中接觸到的Cortex-A8平臺(tái)。見下面列表:

  • FreeScale i.MX51 / i.MX53
  • QualComm msm8x50 / msm7x30
  • Samsung s5pc100 / s5pc110
  • TI omap 3430 / omap 3730
  1. i.MX5 family

    i.MX5 family的介紹見[6][7]。其中i.MX535可以運(yùn)行在800MHZ / 1000MHZ兩種頻率上。

  • i.MX515
    • freq: 800MHZ
    • cache size: 32KB/32KB I/D Cache and 256KB L2 Cache
    • cache line: 64-bit wide(NEON), 64-byte / line
  • i.MX535
  • freq: 800MHZ / 1000MHZ
  • cache size: 32KB/32KB I/D Cache and 256KB L2 Cache
  • cache line: 64-bit wide(NEON), 64-byte / line
  1. Snapdragon family

    Snapdragon的介紹見[8][9][10]。其中msm7x30可以運(yùn)行在800MHZ / 1000MHZ兩種頻率上。此外Snapdragon cache特別之處是128-bit wide(NEON), 128-byte / line。標(biāo)準(zhǔn)Cortex-A8中,該數(shù)值為64-bit wide(NEON), 64-byte / line。這對性能有較大影響。

  • msm8x50
    • freq: 1000MHZ
    • cache size: 32KB/32KB I/D Cache and 256KB L2 Cache
    • cache line: 128-bit wide(NEON), 128-byte / line
  • msm7x30
    • freq: 800MHZ / 1000MHZ
    • cache size: 32KB/32KB I/D Cache and 256KB L2 Cache
    • cache line: 128-bit wide(NEON), 128-byte / line
  1. s5pc family

    s5pc family參考平臺(tái)見[11]。

  • s5pc100
    • freq: 665MHZ
    • cache size: 32KB/32KB I/D Cache and 256KB L2 Cache
    • cache line: 64-bit wide(NEON), 64-byte / line
  • s5pc110
    • freq: 1000MHZ
    • cache size: 32KB/32KB I/D Cache and 512KB L2 Cache
    • cache line: 64-bit wide(NEON), 64-byte / line
  1. omap3 family

    omap3 family參考平臺(tái)見[12][13][14]。

  • omap3430
    • freq: 550MHZ
    • cache size: 16KB/16KB I/D Cache and 256KB L2 Cache
    • cache line: 64-bit wide(NEON), 64-byte / line
  • omap3730
    • freq: 1000MHZ
    • cache size: 32KB/32KB I/D Cache and 256KB L2 Cache
    • cache line: 64-bit wide(NEON), 64-byte / line
  1. memcpy實(shí)現(xiàn)介紹

    memcpy的實(shí)現(xiàn)在ARM平臺(tái)上的發(fā)展有3類版本:

  2. C語言版本
  3. ARM匯編版本
  4. NEON匯編版本

    ARM公司的文檔[4]對memcpy的實(shí)現(xiàn)有很好描述。有人[5][19][20]還進(jìn)一步闡述了實(shí)現(xiàn)原理和技巧。簡述如下:

  • NEON指令一次可以處理64-bit數(shù)據(jù),效率更高。
  • NEON架構(gòu)與L1/L2 cache都有直連,在OS層級(jí)enable后,可以獲得更好的性能。
  • ARM / NEON的pipeline有可能異步處理,交替使用ARM / NEON指令有可能獲得更好的性能。
  • 在一次循環(huán)中,用盡可能多的寄存器copy更多的數(shù)據(jù),保證pipeline有更好的效率。目前一次最大處理塊為128-byte。
  • 對cache的操作有講究。
    • memcpy屬于一次掃瞄無回溯的操作,對于cache采用預(yù)取(preload)策略可以提高h(yuǎn)it rate。所以匯編版本中一定會(huì)使用pld指令提示ARM預(yù)先把cache line填充好。
    • pld指令中的offset很有講究。一般為64-byte的倍數(shù)。在ARMv5TE平臺(tái)是一個(gè)循環(huán)用一個(gè)pld指令。在Cortex-A8平臺(tái)上速度更快,需要一個(gè)循環(huán)用2~3個(gè)pld指令填充cache line。這樣一個(gè)循環(huán)消費(fèi)2~3個(gè)時(shí)鐘周期換得cache hit rate提高,效果是值得的。
    • 進(jìn)一步的,Cortex-A8架構(gòu)提供了preload engine指令,可以讓軟件更深地影響cache,以便讓cache hit rate得到提高。不過要在用戶空間使用ple指令,需要在OS中打補(bǔ)丁開放權(quán)限。

  1. C語言版本

    C語言版本主要是做對比。采用兩個(gè)實(shí)現(xiàn):

  2. 32-bit wide copy。后面標(biāo)記為in32_cpy。
  3. 16-byte wide copy。后面標(biāo)記為vec_cpy。這個(gè)實(shí)現(xiàn)的技巧是采用gcc的向量擴(kuò)展"__attribute__ ((vector_size(16)))",在C語言層級(jí)實(shí)現(xiàn)16-byte wide copy,將具體實(shí)現(xiàn)交給編譯器。

    值得注意的事情是,編譯器不會(huì)主動(dòng)插入pld指令。因?yàn)榫幾g器無法判斷應(yīng)用對內(nèi)存的訪問模式。

  4. ARM匯編版本

    ARM匯編版本也主要是做對比。采用兩個(gè)實(shí)現(xiàn):

  5. Siarhei Siamashka實(shí)現(xiàn)[15]。后面標(biāo)記為arm9_memcpy。他是為Nokia N770做的優(yōu)化。
  6. Nicolas Pitre實(shí)現(xiàn)[16]。后面標(biāo)記為armv5te_memcpy。這是目前glibc里面缺省的arm memcpy實(shí)現(xiàn)。
  7. NEON匯編版本

    NEON匯編版本采用四個(gè)實(shí)現(xiàn):

  8. M?ns Rullg?rd實(shí)現(xiàn)[19]。這是一個(gè)128-byte-align block的最簡單的實(shí)現(xiàn)。沒有判斷不是128-byte align的情況。因此不是實(shí)用的版本。但通過這類實(shí)現(xiàn),可以考察memcpy性能的極限。他總共提供4種實(shí)現(xiàn)。
  9. 全ARM匯編的實(shí)現(xiàn)。后面標(biāo)記為memcpy_arm。此外,筆者還將其中的pld指令去掉,做為對比試驗(yàn),考察pld指令的影響。后面標(biāo)記為memcpy_arm_nopld。
  10. 全NEON匯編的實(shí)現(xiàn)。后面標(biāo)記為memcpy_neon。此外,筆者還將其中的pld指令去掉,做為對比試驗(yàn),考察pld指令的影響。后面標(biāo)記為memcpy_neon_nopld。
  11. ARM / NEON指令交替使用的實(shí)現(xiàn)。后面標(biāo)記為memcpy_armneon。此外,筆者還將其中的pld指令去掉,做為對比試驗(yàn),考察pld指令的影響。后面標(biāo)記為memcpy_armneon_nopld。
  12. ple + NEON的實(shí)現(xiàn)。后面標(biāo)記為memcpy_ple_neon。此外,筆者還將其中的NEON指令換成ARM指令,做為對比試驗(yàn),考察ple指令對ARM/NEON指令的影響。后面標(biāo)記為memcpy_ple_arm。因?yàn)檫@個(gè)實(shí)現(xiàn)需要對linux kernel打補(bǔ)丁,在omap3430平臺(tái)上沒有成功。在Snapdragon平臺(tái)上更換kernel有些麻煩,所以也沒有測試。
  13. CodeSourcery實(shí)現(xiàn)[17]。這是CodeSourcery toolchain中的glibc里面的實(shí)現(xiàn)。也分兩種實(shí)現(xiàn)。
  14. ARM實(shí)現(xiàn)。后面標(biāo)記為memcpy_arm_codesourcery。筆者還將其中的pld指令去掉,做為對比試驗(yàn),考察pld指令的影響。后面標(biāo)記為memcpy_arm_codesourcery_nopld。
  15. NEON實(shí)現(xiàn)。后面標(biāo)記為memcpy_neon_codesourcery。這也是Android bionic里面采用的NEON實(shí)現(xiàn)。筆者還將其中的pld指令去掉,做為對比試驗(yàn),考察pld指令的影響。后面標(biāo)記為memcpy_neon_codesourcery_nopld。
  16. QualComm實(shí)現(xiàn)[18]。后面標(biāo)記為memcpy_neon_qualcomm。這是QualComm在Code Aurora Forum中為Snapdragon平臺(tái)開發(fā)的優(yōu)化版本。主要是對8660/8650A平臺(tái)的優(yōu)化。這個(gè)版本的特點(diǎn)是針對L2 cache line size=128bytes而設(shè)計(jì),pld offset設(shè)置得特別大。結(jié)果在其它Cortex-A8平臺(tái)上沒有效果。所以筆者將pld offset改為M?ns Rullg?rd實(shí)現(xiàn)的數(shù)值。筆者還將其中的pld指令去掉,做為對比試驗(yàn),考察pld指令的影響。后面標(biāo)記為memcpy_neon_qualcomm_nopld。
  17. Siarhei Siamashka實(shí)現(xiàn)[20]。后面標(biāo)記為memcpy_neon_siarhei。這是Siarhei Siamashka向glibc提交的NEON版本,沒有被glibc采納。但是在MAEMO項(xiàng)目中得到采用。這個(gè)版本的特點(diǎn)是pld offset是從小到大增長的,以期望適應(yīng)block size的變化。
  18. 測試方案介紹

    測試方案十分簡單。參考了movial memory tester的實(shí)現(xiàn)[21]。執(zhí)行步驟如下:

  19. 先對每個(gè)實(shí)現(xiàn)進(jìn)行正確性的驗(yàn)證。主要方法是以隨機(jī)的block size & offset,填充隨機(jī)的內(nèi)容,然后執(zhí)行memcpy操作,然后再用系統(tǒng)的memcmp函數(shù)對兩塊內(nèi)存做校驗(yàn)。
  20. 然后對每個(gè)實(shí)現(xiàn)以不同的block size調(diào)用400次。如果total copy size < 1MB,則增加count直到滿足要求。對總操作計(jì)時(shí)。
  21. 以total copy size / total copy time公式計(jì)算memcpy bandwidth。

    上述提到的block size = 2^n ( 7 <= n <= 23 )。

    此外,這個(gè)測試程序運(yùn)行在openembedded-gpe軟件系統(tǒng)中。QualComm / Samsung硬件平臺(tái)只提供Android軟件系統(tǒng),要更換到GPE系統(tǒng)有些麻煩,則采用chroot方式進(jìn)行測試。不論是哪種軟件平臺(tái),都是進(jìn)入到圖形系統(tǒng)后,靜置,等待黑屏,然后再進(jìn)行測試。

    下表是運(yùn)行環(huán)境的統(tǒng)計(jì)。

    硬件平臺(tái)

    軟件環(huán)境

    imx51 800MHZ

    openembedded-gpe

    imx53 1000MHZ

    openembedded-gpe

    imx53 800MHZ

    openembedded-gpe

    msm7230 1000MHZ

    Android + chroot

    msm7230 800MHZ

    Android + chroot

    msm8250 1000MHZ

    Android + chroot

    omap3430 550MHZ

    openembedded-gpe

    omap3730 1000MHZ

    openembedded-gpe

    s5pc100 665MHZ

    Android + chroot

    s5pc110 1000MHZ

    Android + chroot

    下表是測試項(xiàng)目的統(tǒng)計(jì)。

    實(shí)現(xiàn)方案

    i.MX51

    i.MX53

    Snapdragon

    s5pc1xx

    omap3430

    omap3730

    int32_cpy

    YES

    YES

    YES

    YES

    YES

    YES

    vec_cpy

    YES

    YES

    YES

    YES

    YES

    YES

    arm9_memcpy

    YES

    YES

    YES

    YES

    YES

    YES

    armv5te_memcpy

    YES

    YES

    YES

    YES

    YES

    YES

    memcpy_arm

    YES

    YES

    YES

    YES

    YES

    YES

    memcpy_arm_nopld

    YES

    NO

    YES

    YES

    YES

    YES

    memcpy_neon

    YES

    YES

    YES

    YES

    YES

    YES

    memcpy_neon_nopld

    YES

    NO

    YES

    YES

    YES

    YES

    memcpy_armneon

    YES

    YES

    YES

    YES

    YES

    YES

    memcpy_ple_arm

    YES

    YES

    N/A

    YES

    N/A

    YES

    memcpy_ple_neon

    YES

    YES

    N/A

    YES

    N/A

    YES

    memcpy_arm_codesourcery

    YES

    YES

    YES

    YES

    YES

    YES

    memcpy_arm_codesourcery_nopld

    YES

    NO

    YES

    YES

    YES

    YES

    memcpy_neon_codesourcery

    YES

    YES

    YES

    YES

    YES

    YES

    memcpy_neon_codesourcery_nopld

    YES

    NO

    YES

    YES

    YES

    YES

    memcpy_neon_qualcomm

    YES

    YES

    YES

    YES

    YES

    YES

    memcpy_neon_qualcomm_nopld

    YES

    NO

    YES

    YES

    YES

    YES

    memcpy_neon_siarhei

    YES

    YES

    YES

    YES

    YES

    YES

    注1:因?yàn)閕.MX53 EVK板子發(fā)生故障,未能測試所有no pld的測試項(xiàng)。

    注2:在給omap3430打開preload engine后,測試產(chǎn)生非法指令錯(cuò),未能測試ple的測試項(xiàng)。

    注3:要替換Snapdragon kernel有些麻煩,未能測試ple的測試項(xiàng)。

  22. 測試結(jié)果與分析

    下面的圖表限于頁面大小不能很好地顯示細(xì)節(jié)。具體的數(shù)據(jù)和大圖可到數(shù)據(jù)表文檔中查看。

  23. 各個(gè)硬件平臺(tái)上各種實(shí)現(xiàn)的表現(xiàn)

  24. imx51 800MHZ

  25. imx53 1000MHZ

  26. imx53 800MHZ

  27. msm7230 1000MHZ

  28. msm7230 800MHZ

  29. msm8250 1000MHZ

  30. omap3430 550MHZ

  31. omap3730 1000MHZ

  32. s5pc100 665MHZ

  33. s5pc110 1000MHZ

    1. 小結(jié)

  34. 在block size = 512B ~ 32K之間,有一個(gè)性能高臺(tái),block size = 256K也有一個(gè)性能的轉(zhuǎn)折。
  35. 這個(gè)特性體現(xiàn)了32KB L1 / 256KB L2 cache的影響。
  36. 小于512B的性能不佳,可能與函數(shù)調(diào)用,函數(shù)開始的塊對齊技巧造成的損耗有關(guān),也可能與block size太小,cache沒有準(zhǔn)備好函數(shù)就結(jié)束了有關(guān)。
  37. 文檔[]對memcpy的實(shí)現(xiàn)還是有指導(dǎo)意義的。但隨著芯片內(nèi)部的優(yōu)化和工藝的提升,有些規(guī)則發(fā)生了變化。
  38. NEON指令的性能總是要高于ARM指令的性能。但交替使用ARM/NEON指令并不總是帶來性能的提升。隨著發(fā)展ARM/NEON指令之間性能差在縮小。
  39. pld指令的作用越來越小。在較老的芯片上,如omap3430,采用pld指令后,同一個(gè)實(shí)現(xiàn)可以有50%的性能提升。在較新的芯片上,如msm7230/s5pc110上,性能基本沒有區(qū)別,甚至同一個(gè)實(shí)現(xiàn)沒有pld指令后,性能稍稍有些提升。這也許是因?yàn)閜ld指令沒有效果,倒反在每個(gè)循環(huán)中浪費(fèi)了時(shí)鐘周期造成的。
  40. 采用ple指令的實(shí)現(xiàn)的性能令人大失所望。這也說明如果沒有很好的模型設(shè)計(jì),軟件去干預(yù)cache的使用,很容易會(huì)造成性能的惡化。
  41. Snapdragon平臺(tái)有最好的cache性能。超出cache后,各種實(shí)現(xiàn)(包括C語言實(shí)現(xiàn))的性能基本一致,也很高效。這也許是Snapdragon平臺(tái)13-stage load/store pipeline[][]的設(shè)計(jì)造成的。這個(gè)特性對高級(jí)語言是有好處的。因?yàn)榫幊滩豢赡茉诤芏嗟胤讲捎脜R編語言。這樣開發(fā)人員就不必過多地考慮匯編優(yōu)化,依賴編譯器就可以了。
  42. s5pc110平臺(tái)有最好的平均性能。超出cache后,NEON實(shí)現(xiàn)的性能最好,基本保持一條水平線。
  43. 在small/big block size下各個(gè)硬件平臺(tái)的表現(xiàn)

    性能因?yàn)閎lock size分為fit in cache / out of cache兩種表現(xiàn),所以做兩個(gè)剖面做對比分析。

  • 8K block size。體現(xiàn)fit in cache時(shí)的性能。
  • 8M block size。體現(xiàn)out of cache時(shí)的性能。
  1. M?ns Rullg?rd的實(shí)現(xiàn)

    因?yàn)镸?ns Rullg?rd的實(shí)現(xiàn)最簡單,除了一個(gè)循環(huán)體外,沒有其它判斷代碼,可以認(rèn)為是體現(xiàn)平臺(tái)速度極限的實(shí)現(xiàn)。

  2. ARM的實(shí)現(xiàn)

  3. NEON的實(shí)現(xiàn)

  4. 小結(jié)

  5. NEON指令的性能總是要高于ARM指令的性能。隨著發(fā)展ARM/NEON指令之間性能差在縮小。
  6. 交替使用ARM/NEON指令,在fit in cache條件下性能要差于NEON版本。在out of cache條件下,兩個(gè)版本性能基本一樣。
  7. 在fit in cache條件下,Snapdragon平臺(tái)有最好的性能。超過第二名s5pc110大約為43%。
  8. 在out of cache條件下,s5pc110有最好的性能。超過第二名omap3730大約為57%。
  9. 在同一個(gè)硬件平臺(tái)下,超頻(如i.MX53 800/1000MHZ & msm7x30 800/1000MHZ)對memory性能影響很小。
  10. 實(shí)用ARM/NEON實(shí)現(xiàn)在各個(gè)硬件平臺(tái)的表現(xiàn)

    通過同一種實(shí)現(xiàn)在不同硬件平臺(tái)上性能的對比,結(jié)合上一節(jié)的圖表,可以評價(jià)一種實(shí)現(xiàn)的平均性能,也就是適應(yīng)性。

  11. ARM的實(shí)現(xiàn)

  12. NEON的實(shí)現(xiàn)

  13. 小結(jié)

  14. 同一種的實(shí)現(xiàn),在不同的硬件平臺(tái)上都有不同的表現(xiàn)。沒有一種實(shí)現(xiàn)在所有平臺(tái)上是最好的。
  15. Codesourcery版本,包括ARM/NEON版本,有很好的適應(yīng)性。不愧是做toolchain的公司。
  16. Siarhei Siamashka的NEON版本也有很好的適應(yīng)性。NOKIA的技術(shù)實(shí)力也很強(qiáng)。這哥們好像也是pixman項(xiàng)目里面做NEON優(yōu)化的主力。
  17. Qualcomm版本只適合Snapdragon平臺(tái)。期待以后能在msm8660以及后續(xù)的芯片上進(jìn)行測試。
  18. 總結(jié)

  19. 在block size = 512B ~ 32K之間,有一個(gè)性能高臺(tái),block size = 256K也有一個(gè)性能的轉(zhuǎn)折。這個(gè)特性體現(xiàn)了32KB L1 / 256KB L2 cache的影響。
  20. NEON指令的性能總是要高于ARM指令的性能。隨著發(fā)展ARM/NEON指令之間性能差在縮小。交替使用ARM/NEON指令,性能往往要差于NEON版本。
  21. 如果沒有很好的模型設(shè)計(jì),軟件去干預(yù)cache的使用,很容易會(huì)造成性能的惡化。
  22. 在fit in cache條件下,Snapdragon平臺(tái)有最好的性能。
  23. 在out of cache條件下,s5pc110有最好的性能。
  24. 在同一個(gè)硬件平臺(tái)下,超頻對memory性能影響很小。
  25. 同一種的實(shí)現(xiàn),在不同的硬件平臺(tái)上都有不同的表現(xiàn)。沒有一種實(shí)現(xiàn)在所有平臺(tái)上是最好的。
  26. 進(jìn)一步的測試

    因?yàn)樵贑ortex-A8系列芯片里,NEON模塊是必有的。而在Cortex-A9系列芯片里,NEON模塊是可選的。因?yàn)镹EON模塊會(huì)影響到die size,因而影響功耗和成本。因此有些Cortex-A9芯片,如Nvidia Tegra250,沒帶有NEON模塊。那么有無NEON模塊會(huì)對軟件性能造成什么樣的影響呢?



評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉