1. 程式人生 > >FPGA計算效能優化--資料執行優化1

FPGA計算效能優化--資料執行優化1

前一節裡面簡單介紹了資料訪問優化的幾種方式,接下來詳解介紹一下:

1.DATAMotion network:

FPGA的資料傳輸網路是用來連線程式執行在PS端和PL端。SDSOC環境將會自動的建立一個基於資料型別的資料傳輸網路,但是我們可以使用指令來優化執行速率和硬體資源。

常規的資料傳輸型別有:

1Scalar:常量經常通過AXI_lite協議傳輸。

2Array:陣列包含多個數據值,並且可有效的使用高速DMA傳輸協議。SDSOC環境提供了許多選項來控制硬體和資源的有效性,甚至允許特定的傳輸資料格式來應用在硬體上。

3Pointers:預設情況下,如果沒有任何語法,一個指標引數被當作一個常量處理。如果一個指標多次寫入或者讀出,語法上應該保證資料傳輸的高效性。

4Strector class:結構體和類

2.MemoryAllocation/資料分配(關鍵詞,使用sdslib分配連續的記憶體地址)

SDSOC編譯器將會分析你的程式,進而選擇一個合適的資料型別用於在軟體和硬體上使用,資料的型別會根據負載的大小,加速器上的硬體介面和函式引數的屬性而決定。當編譯器可以保證一個數組引數位於連續的實體地址上時,它就可以使用最有效的資料傳輸。使用sds_lib函式庫來分配資料或者記憶體對映陣列時,可以確保編譯器讓記憶體訪問使用連續的地址。eg.

地址分配主要設計到兩條指令:

       1sds_alloc(size_tsize);//使用連續的地址分配記憶體

;使用AXI_DMA_Simple傳輸,該協議在連續地址傳輸上更快。

       2malloc:作為自由變數分配在棧。有助於sdsoc編譯器選擇最佳的資料發;非連續分配記憶體;使用AXI_DMA_SG傳輸

當然有可能由於程式結構的原因,sdscc編譯器不能夠將資料分配到連續的地址上,這時候編譯器會給出一個警告:

Warning:[DMAnalysis83-4492]unable to determine the memory attributes passed to>.......

這時候你可以在需要連續分配地址的程式上加上一下程式碼來儘量是的資料分配是連續的(注意:這個函式並不一定確保是的資料分配是連續的,你必須還的

sds_alloc來分配記憶體資料)

其實在具體資料記憶體分配中,使用的是一下指令:

      3#pragmaSDS datamem_attribute(A:PHYSICAL_CONTIGUOUS)//預設實體地址是非連續的。在函式宣告前必須使用該指令。

該指令的引數中有:

PHYSICAL_CONTIGUOUS:意味著所有記憶體對應相關的ArrayName被分配使用sds_alloc;連續分配記憶體;使用AXI_DMA_Simple傳輸,該協議在連續地址傳輸上更快。

NON_PHYSICAL_CONTIGUOUS:意味著所有記憶體對應相關的ArrayName是使用malloc或作為自由變數分配在棧。有助於sdsoc編譯器選擇最佳的資料發;非連續分配記憶體;使用AXI_DMA_SG傳輸。

3.資料傳輸:(關鍵詞:如何減少資料訪問時間)

1)通常情況下,硬體函式呼叫,涉及到函式引數的輸入輸出的複製。利用一個共享的記憶體模型對於硬體函式的引數而言是可行的,但是需要主要注意的是,在吞吐量爆炸式的傳輸下,從PL埠訪問外部DDR的延時會明顯高於CPU訪問外部DDR(CPU頻率高得多原因?)SDSOC環境通過插入一下函式來宣告共享記憶體:

#pragmaSDS data zero_copy(A[0:<array>])//零拷貝

(2)對於可綜合的硬體功能,從共享記憶體(使用zero_copy函式)讀取/寫入單個數據通常是低效率的。一個更有效的辦法是採用memcpy從記憶體中爆發式地讀/寫資料,並且將資料儲存在本地記憶體中。(先從外地訪問,然後再儲存在片上快取。)

(3)指定資料傳輸型別

對於複製和零拷貝(記憶體共享)記憶體語義,另一個有效的替代辦法是在PL和片外的DDR中傳輸資料,用於記憶體效率最大化。每當你需要非時序的硬體功能,可以使用硬體函式在本地記憶體中儲存資料,用於重複訪問變數。(應用PL端的資源來訪問資料?)例如,在視訊應用程式中通常有資料流入,並且儲存在FPGA記憶體中,用於支援多種訪問視訊流資料的型別。對於陣列資料傳輸,sdscc編譯器通過硬體函式來允許資料流訪問(也就是說,指定索引順序後,每個元素將精確地被訪問一次。)插入一下函式來立即指定函式的原型。

#pragmaSDS data access_pattern(A:SEQUENTIAL)//access pattern,指定傳輸型別=SEQUENTIAL| RANDOM

該指令的引數為:

SEQUENTIAL:資料以流的方式訪問輸,編譯器會生成一個streaminginterface(比如FIFFO

RANDOM:使用RAM來訪問資料

對於陣列作為指標型別傳輸給硬體函式,有時候編譯器可以推斷傳輸的大小,如果不能夠推斷的話,編譯器會給出一下資訊:

WARING[DMAnalysis83-4439]cannot determine data size for argument p of function foo

對此,使用以下特殊的資料傳輸長度:

#pragmaSDS data copy(A[0:L+2*T/3])//scalar arguments L,T to same function

其中需要注意的是同一個資料物件不能夠同時使用zero_copycopy.

5copyzero_copy區別:

COPY指令:將資料在CPU處理器和硬體函式上傳輸

ZERO_ COPY指令:硬體函式通過AXI匯流排訪問共享資料

#pragmaSDS data copy(p[0:array_size])//eg.int *p;引數[<offset> : <length>]引數跟據編譯器能否推斷陣列傳輸的長度,不能推斷的話,需要自己宣告,如果沒有指定長度的話,編譯器會跟據資料傳輸情況判定傳輸的長度。

在每個函式的呼叫基礎上,你可以改變改變資料的傳輸長度,以避免硬體函式在函式定義中不需要通過設定陣列的長度(也就是說,函式引數都應該指明所有的變數大小)

4.datacache coherency/資料快取一致(關鍵詞:注意考慮資料是否有PS埠訪問)

對於每一個由系統要求的傳輸資料,sdscc/sds++編譯器自動生成生成軟體配置程式碼。系統預設的假設是保持在CPU和硬體函式之間的記憶體訪問是一致的。

為了使得記憶體訪問一致性,編譯器可以在傳輸資料到硬體函式之前執行快取重新整理,並將資料從硬體函式傳輸到記憶體之前執行快取失效。(執行快取重新整理,將原始的快取失效,以免新來的資料等待???)(預設操作)

上面的操作的正確性是必要的,但是有時候會影響應用的效能。當你使用Zynqdevece HPports時,當你知道CPU不訪問記憶體(應用程式的正確性不依賴快取記憶體一致性),你可以重寫以上預設。這樣做可以避免不必要的快取重新整理開銷。使用一下API來分配記憶體:

void*sds_alloc_non_cacheable(size_t size)

一個典型的應用就是視訊快取幀是由PL訪問,不由CPU訪問。

5data access patters/資料訪問模式(關鍵詞:函式之間,函式內的資料訪問模式對效能的影響)

由於FPGA的優越效能,FPGA被選中來實現C程式碼。一個FPGA的大規模並行架構允許它執行的操作比一個CPU處理器的固有的順序操作的速度更快。使用者通常都希望利用這一效能。

這裡的重點理解是理解C程式碼中固有的訪問模式對結果可能產生的影響。雖然最受關注的是那些進入和推出硬體功能的訪問模式,但在硬體功能中的任何瓶頸都會對函式的訪問速率產生負面影響,因此考慮函式內的訪問模式也是值得考慮的。

為了突出強調某些資料訪問模式如何對效能產生負面影響,並演示如何使用其他模式來完全支援FPGA的並行性和高效能功能,將在下一節中通過一種影象卷積演算法來闡述。