日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

理解:TI C6000 数据存储处理与性能优化

發(fā)布時(shí)間:2024/10/14 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 理解:TI C6000 数据存储处理与性能优化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ?存儲(chǔ)器之于CPU好比倉(cāng)庫(kù)之于車間。車間加工過(guò)程中的原材料、半成品、成品等均需入出倉(cāng)庫(kù),生產(chǎn)效率再快,如果倉(cāng)庫(kù)周轉(zhuǎn)不善,也必然造成生產(chǎn)阻塞。如同倉(cāng)庫(kù)需要合理地規(guī)劃管理一般,數(shù)據(jù)存儲(chǔ)也需要恰當(dāng)?shù)奶幚砑记蓙?lái)提升CPU的運(yùn)算性能。

? ? ?本文基于TI C6000系列DSP,介紹了與運(yùn)算性能優(yōu)化有關(guān)的存儲(chǔ)器知識(shí)。針對(duì)具體的數(shù)據(jù)存儲(chǔ)問(wèn)題,給出相應(yīng)的代碼優(yōu)化策略,并將容易混淆的概念集中討論。?

?名詞說(shuō)明??

  • EMIF: External Memory Interface
  • PMC: Program Memory Controller
  • DMC: Data Memory Controller
  • SPC: Section Program Counter

?

存儲(chǔ)體沖突Vs存儲(chǔ)別名模糊[1]??

1. 存儲(chǔ)體(bank)沖突

C6000系列各DSP的片內(nèi)存儲(chǔ)器結(jié)構(gòu)有所不同,其中大多數(shù)采用交叉存取式存儲(chǔ)體結(jié)構(gòu),如圖1所示,方框中數(shù)字表示字節(jié)地址。因?yàn)槊總€(gè)bank都是一個(gè)單口存儲(chǔ)器,所以每個(gè)周期對(duì)每個(gè)bank只能有一次訪問(wèn)。例如兩個(gè)short型數(shù)據(jù)a和b,a存放在地址1-2中,b存放在地址8-9中,則程序中不能安排a和b并行存/取,否則會(huì)導(dǎo)致存儲(chǔ)器存取延遲,使流水線暫停一個(gè)周期,在暫停周期中進(jìn)行第二次讀/寫存儲(chǔ)器,這就是存儲(chǔ)體沖突現(xiàn)象。

?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖1 ?4bank交叉存取式存儲(chǔ)器

以16bit short型點(diǎn)積計(jì)算為例:

int dotp(short a[], short b[]);

一個(gè)高效的軟件流水核如下。在最后兩條指令中,用LDW“字加載”命令,一個(gè)周期中同時(shí)加載a[0]、a[1]、b[0]、b[1]。

要使軟件流水不被阻塞,則需保證數(shù)組a和b的并行加載不發(fā)生存儲(chǔ)體沖突。

  • 沖突例子:a首地址=0;b首地址=8N
  • 不沖突例子:a首地址=0;b首地址=8N+4

但是,完全控制數(shù)組和其它對(duì)象在存儲(chǔ)器空間的起始位置并不總是可以做到,尤其是當(dāng)一個(gè)指針作為參數(shù)傳遞給函數(shù)時(shí),調(diào)用這個(gè)函數(shù)的指針參數(shù)可能指向不同的存儲(chǔ)器位置。

如果不能知道數(shù)組a和b在存儲(chǔ)體中的排列信息,則只能肯定a[0-1]和a[2-3]不會(huì)發(fā)生存儲(chǔ)體沖突,同理于b[0-1]和b[2-3]。因此,可以通過(guò)循環(huán)展開的方式,安排a[0-1]和a[2-3]、b[0-1]和b[2-3]進(jìn)行同時(shí)存取,避免了可能的存儲(chǔ)體沖突。循環(huán)展開后的軟件流水核如下:

?

另外,在線性匯編中,可以通過(guò)“.mptr”偽指令,給編譯器提供數(shù)據(jù)的存儲(chǔ)相關(guān)信息,讓編譯器自動(dòng)分析是否會(huì)產(chǎn)生存儲(chǔ)體沖突并調(diào)整指令編排。

2. 存儲(chǔ)別名模糊(alias)

當(dāng)多個(gè)不同的變量名都指向相同的存儲(chǔ)區(qū)域,這時(shí)就發(fā)生別名模糊,也就是說(shuō),對(duì)這些變量進(jìn)行操作的指令可能存在存儲(chǔ)相關(guān)性。指令間的相關(guān)性限制了指令的編排,包括軟件流水編排。

匯編優(yōu)化器假定所有的存儲(chǔ)器引用,都是別名化的(aliased),它把控制權(quán)交給用戶,由用戶提供存儲(chǔ)是否別名的信息。編程者可通過(guò)一個(gè)編譯選項(xiàng)/“restrict”關(guān)鍵詞/兩條線性匯編偽指令來(lái)提供存儲(chǔ)別名的信息。

  • -mt編譯選項(xiàng):表示代碼中沒有存儲(chǔ)別名現(xiàn)象。要仔細(xì)判斷是否能使用-mt,如果代碼使用了別名技術(shù)而又設(shè)置了-mt選項(xiàng),可能會(huì)出現(xiàn)意想不到的結(jié)果。
  • restrict關(guān)鍵詞:在C編程中,對(duì)數(shù)組或指針變量用restrict進(jìn)行聲明,提示編譯器該變量指向的存儲(chǔ)區(qū)域不會(huì)與其它變量指向的存儲(chǔ)區(qū)域發(fā)生重疊。
  • .mdep偽指令:用于明確聲明存儲(chǔ)器相關(guān)。
  • .no_mdep偽指令:告訴匯編優(yōu)化器函數(shù)體中沒有存儲(chǔ)器相關(guān)性出現(xiàn)。

*不要把“存儲(chǔ)別名模糊(存儲(chǔ)器相關(guān))”和“存儲(chǔ)體沖突”兩個(gè)概念混淆,它們有著不同的含義和影響。別名模糊影響程序的正確性(當(dāng)然也可能影響性能),存儲(chǔ)體沖突影響程序的性能。存儲(chǔ)器相關(guān)對(duì)于指令編排影響大于存儲(chǔ)體沖突。

?

存儲(chǔ)器模式Vs數(shù)據(jù)終結(jié)方式[1,2]??

1. 存儲(chǔ)器模式

C6000編譯器支持兩種存儲(chǔ)器模式:小存儲(chǔ)器模式和大存儲(chǔ)器模式。

  • 小存儲(chǔ)器模式:.bss段限制在32kB內(nèi),CPU可用直接尋址方式訪問(wèn).bss段中的所有對(duì)象而無(wú)需改變DP(B14)的值。
  • 大存儲(chǔ)器模式:不限制.bss段大小,但CPU只能通過(guò)寄存器間接尋址訪問(wèn).bss中的數(shù)據(jù),也即需要先將對(duì)象地址讀入寄存器中,這帶來(lái)額外的操作。

當(dāng)全局/靜態(tài)變量(存放于.bss段)超過(guò)32kB,而又希望使用小存儲(chǔ)器模式獲得快的訪問(wèn)速度,有兩種解決辦法:

  • 對(duì)于大的數(shù)組定義,使用far關(guān)鍵字,如此數(shù)據(jù)不占用.bss段空間,而放入.far段。
  • 使用-ml/-ml0選項(xiàng),編譯器自動(dòng)對(duì)集合數(shù)據(jù)類型(如結(jié)構(gòu)體和數(shù)組)使用far存取。

?

2. 數(shù)據(jù)終結(jié)方式

指的是多字節(jié)數(shù)據(jù)內(nèi)部高低有效位的存放順序。C6000支持兩種終結(jié)方式:小端終結(jié)方式和大端終結(jié)方式。

  • 小端終結(jié)(Little-Endian):數(shù)據(jù)高有效位字節(jié)存放在地址高位字節(jié)(高位高地址)。
  • 大端終結(jié)(Big-Endian):數(shù)據(jù)高有效位字節(jié)存放在地址低位字節(jié)(高位低地址)。

?

內(nèi)存邊界對(duì)齊[1,3] ?

C67X DSP支持單次存/取16bit(半字)、32bit(字)、64bit(雙字)數(shù)據(jù),但前提是數(shù)據(jù)的存放分別滿足半字對(duì)齊、字對(duì)齊和雙字對(duì)齊。目前C64X支持在非對(duì)齊情況下單次存/取32bit和64bit寬度的數(shù)據(jù)。

所謂半字對(duì)齊指的是數(shù)據(jù)地址的最低1位為0;字對(duì)齊指的是數(shù)據(jù)地址的最低2位為0;雙字對(duì)齊指的是數(shù)據(jù)地址的最低3位為0。

對(duì)不支持非對(duì)齊單次存/取的器件來(lái)說(shuō),如果讓CPU用多字節(jié)存/取指令一次操作非對(duì)齊的數(shù)據(jù),將會(huì)產(chǎn)生額外操作,有些處理器甚至無(wú)法處理而產(chǎn)生錯(cuò)誤!下圖給出了一個(gè)處理示例,從圖中可見,原本單次可以完成的操作由于數(shù)據(jù)未能對(duì)齊而花費(fèi)了5次操作。

? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖2 ?對(duì)非對(duì)齊數(shù)據(jù)進(jìn)行多字節(jié)訪問(wèn)

在C64X中,數(shù)組均默認(rèn)安排8字節(jié)(雙字)對(duì)齊;在C62X和C67X中,數(shù)組按4字節(jié)/8字節(jié)對(duì)齊。

結(jié)構(gòu)體的對(duì)齊方式由其最大數(shù)據(jù)類型成員決定,結(jié)構(gòu)體占用的存儲(chǔ)空間總是最大成員類型大小的倍數(shù)(注意并不是簡(jiǎn)單地乘以成員個(gè)數(shù))。如下兩個(gè)結(jié)構(gòu)體A和B,它們所占的存儲(chǔ)空間分別是8、12。

struct A

{

? ?short x;

??? short y;

??? int z;

}

?

struct B

{

??? short x;

??? int y;

??? short z;

}

數(shù)據(jù)集邊界對(duì)齊并不意味著它里面的每一個(gè)元素的地址都為對(duì)齊長(zhǎng)度的倍數(shù),而是保證數(shù)據(jù)集的起始地址和<結(jié)束地址+1>為對(duì)齊長(zhǎng)度的倍數(shù)。

對(duì)齊的存儲(chǔ)器訪問(wèn)

在C/C++代碼中,有三個(gè)pragma預(yù)編譯語(yǔ)句可以用來(lái)指示編譯器將具體的數(shù)據(jù)按指定的方式進(jìn)行對(duì)齊存儲(chǔ)。

  • DATA_ALIGN:將數(shù)據(jù)進(jìn)行2的整數(shù)次冪對(duì)齊
  • DATA_MEM_BANK:將數(shù)據(jù)對(duì)齊到指定的bank
  • STRUCT_ALIGN(C特有):用于指定結(jié)構(gòu)體、聯(lián)合體進(jìn)行2的整數(shù)次冪對(duì)齊

使用_nassert()內(nèi)聯(lián)函數(shù)能夠指示編譯器某一數(shù)據(jù)的內(nèi)存對(duì)齊狀態(tài)。如

_nassert( ((int)sum & 0x3) == 0);

告訴編譯器sum為字邊界對(duì)齊,有了這個(gè)信息,編譯器就可以放心地安排SIMD(單指令多數(shù)據(jù))指令對(duì)數(shù)據(jù)進(jìn)行操作,但_nassert本身不產(chǎn)生任何操作。

可以使用_amemXX()和_amemXX_const()內(nèi)聯(lián)函數(shù)對(duì)對(duì)齊的字和半字進(jìn)行訪問(wèn)。一般這類內(nèi)存訪問(wèn)可以與_hi()、_lo()和_itod()等數(shù)據(jù)解包和打包內(nèi)聯(lián)函數(shù)聯(lián)合使用。

?

非對(duì)齊的存儲(chǔ)器訪問(wèn)

C64X支持非對(duì)齊的字和雙字訪問(wèn),其對(duì)邊界對(duì)齊和非邊界對(duì)齊數(shù)據(jù)訪問(wèn)的比較如下表所示:

?

從上表可以看出,C64X在每時(shí)鐘周期只能進(jìn)行一次非邊界對(duì)齊的存儲(chǔ)器訪問(wèn),因此,只要可能應(yīng)盡量使用邊界對(duì)齊的存儲(chǔ)器訪問(wèn)方式。

在C/C++代碼中,可以使用_memXX()和_memXX_const()內(nèi)聯(lián)函數(shù)對(duì)非對(duì)齊的字和半字進(jìn)行訪問(wèn)。一般這類內(nèi)存訪問(wèn)可以與_hi()、_lo()和_itod()等數(shù)據(jù)解包和打包內(nèi)聯(lián)函數(shù)聯(lián)合使用,下面是一個(gè)使用示例:

?

?

C6000 Cache(緩存)[4,5]??

為什么需要Cache?

大容量的存儲(chǔ)器(如DRAM)訪問(wèn)速度受到限制,一般比CPU時(shí)鐘速度慢很多;小容量的存儲(chǔ)器(如SRAM)能提供快速的訪問(wèn)速度。因此很多高性能的處理器都提供分層的存儲(chǔ)訪問(wèn)架構(gòu)。

如圖3所示,左右分別是平坦式存儲(chǔ)器架構(gòu)和2層cache的多層存儲(chǔ)架構(gòu)。在左邊的架構(gòu)中,即使CPU能運(yùn)行在600MHz,但由于片內(nèi)/片外存儲(chǔ)器只能運(yùn)行在300MHz/100MHz,CPU在訪問(wèn)存儲(chǔ)時(shí)需插入等待周期。


? ? ? ? ? ? ? ? ? ? ? ? ?圖3 ?平坦式和層級(jí)式存儲(chǔ)器架構(gòu)

Cache部分工作狀態(tài)說(shuō)明

  • Cache hit(緩存命中):對(duì)于已經(jīng)緩存的程序/數(shù)據(jù),訪問(wèn)將引起緩存命中,緩存中的指令/數(shù)據(jù)立即送入CPU而無(wú)需等待。
  • Cache miss(緩存缺失):發(fā)生缺失時(shí),首先通過(guò)EMIF讀入需要的指令/數(shù)據(jù),指令/數(shù)據(jù)在送入CPU的同時(shí)被存入Cache,讀入程序/數(shù)據(jù)的過(guò)程CPU被掛起。
  • Cache flush(緩存命中):清空Cache已經(jīng)緩存的數(shù)據(jù)。
  • Cache freeze(緩存凍結(jié)):Cache內(nèi)容不再改變,發(fā)生缺失時(shí),從EMIF中讀入的指令包不會(huì)同時(shí)存入Cache。
  • Cache bypass(緩存旁路):Cache內(nèi)容不再改變,任何程序/數(shù)據(jù)都將從緩存外存儲(chǔ)器訪問(wèn)。

?

C6000的存儲(chǔ)架構(gòu)

C6000系列DSP在片內(nèi)RAM和CPU之間提供兩層Cache L1和L2,每層Cache又分為獨(dú)立的程序Cache和數(shù)據(jù)Cache。其中L1是固定的,L2可以被重映射為普通片內(nèi)RAM。

對(duì)程序/數(shù)據(jù)進(jìn)行訪問(wèn)時(shí),CPU首先到L1 Cache中尋找,命中則直接訪問(wèn),如果產(chǎn)生缺失,則繼續(xù)在L2Cache中尋找,如果還未命中,則到片內(nèi)RAM或片外RAM中尋址數(shù)據(jù)。


? ? ? ? ? ? ? ? ? ? ? ? ?圖4 ?C6000 CPU的程序/數(shù)據(jù)訪問(wèn)流程

訪問(wèn)定位的規(guī)律

由圖4可知,要保證CPU的存儲(chǔ)訪問(wèn)效率,只有在CPU在大部分的訪問(wèn)都是只針對(duì)最靠近它的存儲(chǔ)區(qū)時(shí)才有效。幸運(yùn)的是,根據(jù)訪問(wèn)定位的規(guī)律,這一條可以保證。訪問(wèn)的定位規(guī)律表明程序在一個(gè)相對(duì)小的時(shí)間窗口對(duì)僅需要一個(gè)相對(duì)較小size的數(shù)據(jù)和代碼。數(shù)據(jù)定位的兩條規(guī)律:

  • 空間關(guān)聯(lián)性:當(dāng)一個(gè)數(shù)據(jù)被訪問(wèn)時(shí),它臨近的數(shù)據(jù)又很大可能會(huì)被后續(xù)的存儲(chǔ)訪問(wèn)。
  • 時(shí)間關(guān)聯(lián)性:一個(gè)存儲(chǔ)區(qū)被訪問(wèn)時(shí),在下一個(gè)臨近的時(shí)間點(diǎn)還會(huì)被訪問(wèn)。

優(yōu)化cache性能

從訪問(wèn)定位規(guī)律出發(fā),可總結(jié)出優(yōu)化cache性能的一些基本準(zhǔn)則:

  • 讓函數(shù)盡可能充分的對(duì)數(shù)據(jù)處理以提高數(shù)據(jù)的重用。
  • 組織數(shù)據(jù)和代碼以提高cache命中率。
  • 合理的空間劃分來(lái)平衡程序cache和數(shù)據(jù)cache。
  • 組合那些對(duì)相同數(shù)據(jù)進(jìn)行處理的函數(shù)在一個(gè)存儲(chǔ)區(qū)域。

?

?段[1,6]??

目標(biāo)文件(.obj)的最小單位稱為段,它是占據(jù)一個(gè)連續(xù)空間的代碼塊或者數(shù)據(jù)塊。連接器的功能之一就是把段重定位到目標(biāo)系統(tǒng)的存儲(chǔ)器映像圖中。所有段都可以獨(dú)立重定位,用戶可以把任一段置入目標(biāo)存儲(chǔ)器任一指定塊內(nèi)。

一個(gè)COFF文件包含三個(gè)默認(rèn)段:.text、.data、.bss。用戶還可以創(chuàng)建、命名、連接自己的段,也可以繼續(xù)在各個(gè)段中繼續(xù)劃分子段。

在C/C++代碼中,有兩個(gè)預(yù)編譯語(yǔ)句可用來(lái)將特定的代碼或數(shù)據(jù)分配到指定的段中:

  • CODE_SECTION:為代碼分配段。
  • DATA_SECTION:為數(shù)據(jù)分配段。

?

棧和堆[1,6]

棧(.stack)和堆(.heap)是為處理器運(yùn)行時(shí)提供支持的兩個(gè)存儲(chǔ)區(qū)。

棧是由編譯器在需要時(shí)分配的,不需要時(shí)自動(dòng)清除的變量存儲(chǔ)區(qū)。它用于存放局部變量、函數(shù)參數(shù)等臨時(shí)數(shù)據(jù)。

堆用于動(dòng)態(tài)內(nèi)存分配。堆在內(nèi)存中位于bss區(qū)和棧區(qū)之間。一般由程序員分配和釋放,若程序員不釋放,程序結(jié)束時(shí)有可能由OS回收。例如C中常用的malloc()函數(shù)就是在堆中開辟區(qū)間存放數(shù)據(jù)。

?

參考文獻(xiàn)/資料??

1】田黎育,何佩琨,朱夢(mèng)宇. TMS320C6000系列DSP編程工具與指南[M].北京:清華大學(xué)出版社 2006.

2】董言治,婁樹理,劉松濤. TMS320C6000系列DSP系統(tǒng)結(jié)構(gòu)原理與應(yīng)用教程[M]. 清華大學(xué)出版社, 2014.

3Data alignment: Straighten up and fly right - IBM developerworks.

4Cache memory – Wikipedia.

5】如何優(yōu)化使用C6000系列C64xCache--原理,Cache種類和優(yōu)化策略 - nouth的網(wǎng)易博客

6C語(yǔ)言中內(nèi)存分配 - youoranCSDN專欄.

轉(zhuǎn)載于"http://www.cnblogs.com/ncdxlxk/p/9221116.html"

?

總結(jié)

以上是生活随笔為你收集整理的理解:TI C6000 数据存储处理与性能优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。