今天讀了一篇RTAS09(嵌入式方面國際頂級會議)年的論文,很有啟發,在此記錄下來。
---------------------------------------------------------------------------------------------------------------------
論文:Minimizing WCET for Real-Time Embedded Systems
via Static Instruction Cache Locking
---------------------------------------------------------------------------------------------------------------------
首先該論文解決的問題是降低一個程式執行的最壞執行時間(WCET, worst case execution time),因為這對於嵌入式系統(即時)有很重要的影響。指令Cache能夠提升讀取指令的平均訪問時間,但在一定程度上,因為讀取Cache的命中不確定性,使得程式執行時間反而更加不可預測。所以有時候甚至會選擇不使用指令Cache來提高對執行時間的可預測性(即時系統必須保證程式能在所要求時間裡面執行完成)。不過現在很多CPU都提供了對於指令Cache的鎖定功能,即可以讓某段代碼一直存在於Cache裡面不會被替換出去。
然而I-Cache的大小總是有限的,那麼怎麼選擇程式中的哪些代碼(或者函數)被鎖在指令Cache裡面,來使得WCET最小(問題1)。
論文對程式的執行建立了一個EFT(execution flow tree)模型,看一個例子就知道EFT表示什麼意思:
if (!data_file) {<br />print_usage();<br />exit(1);<br />}<br />if (search_far_field == 1) {<br />4 if (search_far_field == 1)<br />search_far_<br />exit( ) 3 field_angles()<br />print_usage( ) 2<br />1 if (!data_file)<br />max_energy = search_far_field_angles(max_result, data_file, output_file, hamming);<br />} else if (hill_climb == 1) {<br />search_grid(source_location, data_file, output_file, hamming);<br />} else {<br />calc_single_pos(source_location, mic_locations, hamming, data_file, output_file);<br />}<br />exit(0);
這段代碼對應的EFT:
當然,對於節點2、5、8、9沒有遞迴地展開。
註:我這裡對EFT就簡單通過這個例子說明,具體的定義等可以參考論文
這樣我們可以在編譯的時候通過一個演算法(可以構造)得到程式的執行EFT(V,E),V是節點集,E是邊集。
著重要說明的是V表示的是具體的執行路徑上的節點,並非是真正的實體代碼。什麼意思呢,就是說不同的節點i和節點j,他們可能是同一個函數的執行節點,這完全有可能,不同路徑調用同一個函數(我們給的例子沒有出現這種情況)。
因此我們有必要在定義一個函數(代碼)集F來表示正真的代碼節點
對於節點i屬於V,我們可以定義一些u的屬性:
W(i) 表示函數(代碼)i如果在記憶體中的執行時間
W'(i) 表示函數i如果在I-Cache中的執行時間
name(i) 表示執行節點i對應的函數(代碼)節點,f=name(i)
s(f) 表示函數f所佔的位元組大小
由此:我們可以將問題1抽象為下面問題2
給定一個大小為S的I-Cache,一個EFT(V,E)圖與函數集F,將大小不超過S的函數集X(X包含於F)放入I-Cache,使得EFT(V,E)中最長執行路徑最短。(問題2)
P是所有執行路徑集合,num(Pi)是路徑i的長度,約束條件s.t.第一條其實就是L取所有執行路徑長度的最大值。執行路徑Pi上每個節點j要麼取W(Pij),要麼取W'(Pij),看&(f)(那個符號打不出)的取值(即f是否在I-Cache中),就是 (1-&(f))*W(pij) + &(f)*W'(pij)。
得到一個整數規劃問題,論文中證明這是一個NP-Hard問題。因此有些研究者使用了一些貪心演算法或者遺傳演算法來計算近似解。
這篇論文對該問題添加了一些限制條件,在一定條件能在多項式時間裡求解出最優解。
限制:每個函數不會出現在不同的執行節點中,即節點i和節點j,如果i!=j,那麼name(i)!=name(j)
這表明函數不會reuse。也就是說如果選擇節點i進入I-Cache,那麼不會存在另外一個節點j,使得它的執行時間也從W(j)變成W'(j)。
我們將多叉樹EFT(V,E)轉化為與其等價的二叉樹BEFT(V,E') (標準演算法,第一個孩子是左孩子,後面第一個兄弟是右孩子)
該問題可以用動態規劃來解決。首先我們定義子問題:
OPT[v][i]表示以v為根的那棵子樹,當有大小為i的I-Cache可以使用時,所達到的最小WCET。這樣就有 |V|*|S+1|個子問題(S+1包含了i=0的情況)。
當前已經得到節點v的孩子的OPT,那麼如果轉移求解子問題OPT[v][i]:
1.如果v不包含進I-Cache
那麼可以將大小為i的Cache分給兩個孩子為根的子樹,枚舉左孩子子樹使用Cache大小為j,那麼右子樹可以使用i-j大小的Cache。注意右子樹在EFT中是v的右邊第一個兄弟,所以不需要加W(v),因為和v不在同一執行路徑中。故要使得兩條路徑中最大值最小。
2.如果v包含進I-Cache
那麼v使用掉大小為s(v)的Cache,枚舉給左孩子的Cache大小j,那麼右孩子可以使用i-s(v)-j大小的Cache。
在1和2中取小的組成OPT[v][i],得
DP轉移方程:
(問題三)
其中a(v)=0表示v不包含進I-Cache,a(v)=1表示v包含進I-Cache。在O(|V|*|S|*|S|)複雜內得解。
這裡求出的OPT(v,i)是BEFT中以v為根的子樹的優解,在EFT中該OPT(v,i)表示所有以v為根或者以v的右邊所有兄弟為根的子樹的最優解中的最大值。
一些啟示:
1.RTAS是頂級會議,可見這篇論文的品質,雖然我沒有把這篇論文所有貢獻都寫出來,但是也列出了些核心內容。說明頂級會議並不是那麼遙不可及(^_^)。
2.這篇論文與其說討論體繫結構方面或者嵌入式方面,不如說是一篇純討論演算法的論文,建立模型,然後對模型的分析和求解。今後也可以考慮在體繫結構研究中使用抽象建模的方式來量化分析或者最佳化分析一些問題。