一.Xilinx Zynq-7000帶來(lái)新的設(shè)計(jì)思路
在以前,我們的單板上往往有CPU和多片FPGA,由CPU完成系統(tǒng)的配置和管理,F(xiàn)PGA完成特定算法的硬件加速,受限于CPU和FPGA之間的通信帶寬和延遲,CPU和FPGA之間的接口大多是用于配置和管理,無(wú)法傳輸大量的數(shù)據(jù)。
Xilinx推出的Zynq-7000系列芯片很好的解決了這一問(wèn)題。它內(nèi)含硬化好的CPU核和常見(jiàn)的外設(shè)(DRAM控制器,千兆以太網(wǎng),USB 2.0 OTG,SD card控制器,F(xiàn)LASH控制器,UART,CAN,SPI,I2C等等 ),這一部分被稱為Processing System(簡(jiǎn)稱PS),它可以完全獨(dú)立于FPGA運(yùn)行;Zynq-7000芯片內(nèi)部還有容量不等的FPGA資源,被稱為Programmable Logic(簡(jiǎn)稱PL),可以支持不同復(fù)雜度的邏輯設(shè)計(jì)。最重要的是,在PS和PL之間,有超過(guò)3000根的互聯(lián)信號(hào),包括9路AXI通道,可以提供大約100Gb/s的通信帶寬,同時(shí)在PS和PL之間還有DMA,Interrupt和EMIO等多種資源。這就使得數(shù)據(jù)可以在PS和PL之間靈活高效的遷移,從系統(tǒng)設(shè)計(jì)的角度上來(lái)講,任務(wù)可以在軟件和硬件之間靈活的分割,實(shí)現(xiàn)高度優(yōu)化的系統(tǒng)設(shè)計(jì)。這也給嵌入式系統(tǒng)的開(kāi)發(fā)方法提供了新的思路和流程:首先利用軟件可以快速靈活編程的特點(diǎn),快速的用軟件實(shí)現(xiàn)系統(tǒng)的原型;然后通過(guò)對(duì)軟件進(jìn)行profiling找出對(duì)系統(tǒng)性能影響最大的代碼,將這部分代碼用FPGA來(lái)硬件加速,實(shí)現(xiàn)高度優(yōu)化的嵌入式系統(tǒng);Xilinx還提供了HLS(High Level Synthesis)工具可以方便快速的把軟件代碼轉(zhuǎn)化成RTL代碼,幫助開(kāi)發(fā)者快速的實(shí)現(xiàn)基于FPGA的硬件加速器。
在這一流程中,重要的一環(huán)是如何找出軟件中對(duì)性能影響最大的那部分代碼。對(duì)于簡(jiǎn)單的應(yīng)用,我們可以很容易的判斷出來(lái),例如對(duì)頻譜分析來(lái)說(shuō),F(xiàn)FT算法就是最至關(guān)重要的需要優(yōu)化的算法。但是在很多時(shí)候,軟件非常復(fù)雜,有很多的復(fù)雜的函數(shù)調(diào)用,很難通過(guò)靜態(tài)的觀察和分析找出對(duì)性能影響最大的那部分代碼,這時(shí)就需要通過(guò)profiling工具,在軟件動(dòng)態(tài)運(yùn)行中收集數(shù)據(jù),通過(guò)統(tǒng)計(jì)的方法找出核心代碼了。
二.Profiling的對(duì)象
在Linux下有很多profiling工具,各自有自己的優(yōu)勢(shì)和劣勢(shì)。在這里我們重點(diǎn)研究一下如何使用gprof對(duì)軟件做profiling。
很多介紹profiling工具的文章都是開(kāi)發(fā)者自己寫一個(gè)簡(jiǎn)單源文件,里面有簡(jiǎn)單的函數(shù)調(diào)用。
為了更好的展示profiling的效果,這里我們沒(méi)有采用這種方法,而是采用了一個(gè)相對(duì)比較復(fù)雜的軟件包libjpeg。
libjpeg 是一個(gè)完全用C語(yǔ)言編寫的庫(kù),包含了被廣泛使用的JPEG解碼、JPEG編碼和其他的JPEG功能的實(shí)現(xiàn)。這個(gè)庫(kù)由獨(dú)立JPEG工作組維護(hù)。編譯完成后除了相應(yīng)的.a和.so庫(kù)文件之外,還會(huì)生成以下工具程序:
cjpeg和djpeg:用于JPEG的壓縮和解壓縮,可以和一些其他格式的圖形文件進(jìn)行轉(zhuǎn)換。
rdjpgcom和wrjpgcom:用于在JFIF文件中插入和提取文字信息。
jpegtran:一個(gè)用于在不同的JPEG格式之間進(jìn)行無(wú)損轉(zhuǎn)換的工具。
在這里cjpeg和djpeg就是很不錯(cuò)的profiling對(duì)象,有一定的復(fù)雜度,但又沒(méi)有復(fù)雜到令人生畏。JPEG圖像文件可以在互聯(lián)網(wǎng)上靈活選取,基本原則是足夠大,這樣可以有比較長(zhǎng)的運(yùn)行時(shí)間來(lái)收集profiling數(shù)據(jù),同時(shí)有足夠的細(xì)節(jié)可以讓軟件充分的運(yùn)行起來(lái)。網(wǎng)站 上有很多大的圖片,筆者選擇的是一個(gè)2880x1800的JPEG文件。
Libjpeg可以在 上找到。這里使用的版本是13-Jan-2013發(fā)布的release 9。下載后的源文件是jpegsrc.v9.tar.gz
三. GNU profiler(gprof)簡(jiǎn)介
GNU profiler(gprof)是GNU Binutils( https://sourceware.org/binutils/ )的一個(gè)組成部分,詳細(xì)的文檔可以在 https://sourceware.org/binutils/docs/gprof/ 找到,默認(rèn)情況下Linux系統(tǒng)當(dāng)中都帶有這個(gè)工具,不過(guò)如果打算在嵌入式開(kāi)發(fā)板上用還是需要對(duì)GNU Binutils做交叉編譯的。
Gprof的功能:
1. 生成“flat profile”,包括每個(gè)函數(shù)的調(diào)用次數(shù),每個(gè)函數(shù)消耗的處理器時(shí)間,
2. 生成“Call graph”,包括函數(shù)的調(diào)用關(guān)系,每個(gè)函數(shù)調(diào)用花費(fèi)了多少時(shí)間。
3. 生成“注釋的源代碼”,即是程序源代碼的一個(gè)復(fù)本,標(biāo)記有程序中每行代碼的執(zhí)行次數(shù)。
Gprof的原理:
通過(guò)在編譯和鏈接時(shí)使用 -pg選項(xiàng),gcc 在應(yīng)用程序的每個(gè)函數(shù)中都加入了一個(gè)名為mcount (也可能是”_mcount”或者”__mcount”, 依賴于編譯器或操作系統(tǒng))的函數(shù),這樣應(yīng)用程序里的每一個(gè)函數(shù)都會(huì)調(diào)用mcount, 而mcount 會(huì)在內(nèi)存中保存一張函數(shù)調(diào)用圖,記錄通過(guò)函數(shù)調(diào)用堆棧找到的子函數(shù)和父函數(shù)的地址,以及所有與函數(shù)相關(guān)的調(diào)用時(shí)間,調(diào)用次數(shù)等信息。
Gprof基本使用流程
1. 在編譯和鏈接時(shí)加上-pg選項(xiàng)。一般可以加在 Makefile 中的CFLAGS和LDFLAGS中。
2. 執(zhí)行編譯的二進(jìn)制程序。執(zhí)行參數(shù)和方式同以前。
3. 正常結(jié)束進(jìn)程。這時(shí)內(nèi)存中的信息會(huì)被寫入到程序運(yùn)行目錄下的gmon.out 文件中。
4. 用 gprof 工具分析 gmon.out 文件。
Gprof參數(shù)說(shuō)明
? -b 不再輸出統(tǒng)計(jì)圖表中每個(gè)字段的詳細(xì)描述。
? -p 只輸出函數(shù)的調(diào)用圖(Call graph的那部分信息)。
? -q 只輸出函數(shù)的時(shí)間消耗列表。
? -e Name 不輸出函數(shù)Name 及其子函數(shù)的調(diào)用圖(除非它們有未被限制的其它父函數(shù))??梢越o定多個(gè)-e 標(biāo)志。一個(gè) -e 標(biāo)志只能指定一個(gè)函數(shù)。
? -E Name 不輸出函數(shù)Name 及其子函數(shù)的調(diào)用圖,此標(biāo)志類似于 -e 標(biāo)志,但它在總時(shí)間和百分比時(shí)間的計(jì)算中排除了由函數(shù)Name 及其子函數(shù)所用的時(shí)間。
? -f Name 輸出函數(shù)Name 及其子函數(shù)的調(diào)用圖??梢灾付ǘ鄠€(gè) -f 標(biāo)志。一個(gè) -f 標(biāo)志只能指定一個(gè)函數(shù)。
? -F Name 輸出函數(shù)Name 及其子函數(shù)的調(diào)用圖,它類似于 -f 標(biāo)志,但它在總時(shí)間和百分比時(shí)間計(jì)算中僅使用所打印的例程的時(shí)間??梢灾付ǘ鄠€(gè) -F 標(biāo)志。一個(gè) -F 標(biāo)志只能指定一個(gè)函數(shù)。-F 標(biāo)志覆蓋 -E 標(biāo)志。
一般用法:
gprof -b ELF_file_name gmon.out >report.txt
Gprof報(bào)告中flat profile表格各列的說(shuō)明:
%time: 該函數(shù)消耗時(shí)間占程序所有時(shí)間百分比,全部相加應(yīng)該是100%。
Cumulative seconds: 程序的累積執(zhí)行時(shí)間,包括表格內(nèi)該函數(shù)所在行之上的所有函數(shù)的執(zhí)行時(shí)間
Self Seconds: 該函數(shù)本身的全部執(zhí)行時(shí)間。表格會(huì)依照這列的數(shù)值按照降序排序所有行
Calls: 函數(shù)被調(diào)用次數(shù), 如果無(wú)法確定則為空。
Self ms/call: 函數(shù)平均執(zhí)行時(shí)間。
Total ms/call: 函數(shù)平均執(zhí)行時(shí)間, 包括其內(nèi)部調(diào)用。
Name: 函數(shù)名。在按照self seconds和calls排序后再依照這列進(jìn)行字母排序。
Gprof報(bào)告中Call Graph表格各列的說(shuō)明:
Index: 索引值
%time: 函數(shù)消耗時(shí)間占所有時(shí)間百分比
Self: 函數(shù)本身執(zhí)行時(shí)間
Children: 執(zhí)行子函數(shù)所用時(shí)間
Called: 被調(diào)用次數(shù)
Name: 函數(shù)名
Gprof的優(yōu)勢(shì):
1. 簡(jiǎn)單易用。只需要在編譯和鏈接是增加-pg選項(xiàng)。gprof對(duì)于代碼大部分是用戶空間的CPU密集型的應(yīng)用程序用處明顯,對(duì)于大部分時(shí)間運(yùn)行在內(nèi)核空間或者由于外部因素(例如操作系統(tǒng)的 I/O 子系統(tǒng)過(guò)載)而運(yùn)行緩慢的應(yīng)用程序則意義不大。
2. GNU Binutils的組成部分,基本上任何Linux里面都有??梢园焉傻膅mon.out拷貝到host上進(jìn)行分析,省掉了一部分交叉編譯的工作量。
Gprof的劣勢(shì):
1. Gprof只夠監(jiān)控到編譯和鏈接時(shí)有-pg選項(xiàng)的函數(shù),工作在內(nèi)核態(tài)的函數(shù)和沒(méi)有加-pg編譯的第三方庫(kù)函數(shù)是無(wú)法被gprof監(jiān)控到的。因此Gprof比較適合執(zhí)行時(shí)間大部分在用戶態(tài)的應(yīng)用。在使用Gprof前最好用Linux下的time命令來(lái)確認(rèn)應(yīng)用程序的實(shí)際運(yùn)行時(shí)間、用戶空間運(yùn)行時(shí)間、內(nèi)核空間運(yùn)行時(shí)間,以判斷是否合適用gprof。Oprofile可以解決這一問(wèn)題。
2. Gprof不能監(jiān)控shared library,即.so的文件。
對(duì)此有詳細(xì)的分析。對(duì)這類文件可以用sprof,不過(guò)并不好用。變通的辦法是將library靜態(tài)鏈接到應(yīng)用中,這樣會(huì)增加應(yīng)用程序的code size。
3. Gprof 不支持多線程應(yīng)用,多線程下只能采集主線程性能數(shù)據(jù)。原因是在多線程內(nèi)只有主線程才能響應(yīng)gprof采用的ITIMER_PROF信號(hào)。有一個(gè)簡(jiǎn)單的方法可以解決這一問(wèn)題:
4. gprof只能在程序正常結(jié)束退出,或者通過(guò)系統(tǒng)調(diào)用exit()退出之后才能生成報(bào)告(gmon.out)。原因是gprof通過(guò)在atexit()里注冊(cè)了一個(gè)函數(shù)來(lái)產(chǎn)生結(jié)果信息,任何非正常退出都不會(huì)執(zhí)行atexit()的動(dòng)作,所以不會(huì)產(chǎn)生gmon.out文件。
5. 函數(shù)執(zhí)行時(shí)間是估計(jì)值。函數(shù)執(zhí)行時(shí)間是通過(guò)采樣估算的, 在執(zhí)行時(shí)間足夠長(zhǎng)的情況下,這個(gè)不是什么大的問(wèn)題,一般估算值與實(shí)際值相差不大。
評(píng)論