2009年10月15日 星期四

MPEG-4 code SIMD 化 -- 雙魚

=========== 2009.10.15===========

還是拿原本的code來改 , 主要把第一次改的換種方法
以及 找了第二個可以改成SIMD的部分

(1) 第一部分的別種方法:

->本來的方法是圖的上半部 , vector先裝入IDCT_Coeffo [0~3]的數值
讓IDCT_Coeffo 和 V0 相乘結果先暫存在 temp
再把暫存在 temp中的四個數值相加後放進去R0[i]
R0[i] = temp[0] + temp[1] + temp[2] + temp[3] ;
老師有提過 這邊一堆+ 可能會影響速度 , 所以換種方法


-> 後來的方法是圖的下半部 , 先把 IDCT_Coeffo 陣列轉置
轉置的結果IDCT_Coeffo 陣列順序變成 0 4 8 12 ......
讓vector先裝入IDCT_Coeffo [0 4 8 12] 的數值 再和V0相乘
相乘的結果就可以直接放入R0[0~3] 中

下次vector則裝入IDCT_Coeffo [1 5 9 13] 的數值 再和V0相乘
相乘的結果直接和上一次的R0[0~3] 累加 , 使用vec_madd()去累加


(2) 第二部分的改寫 原始code如下 :

for(i = 0; i <= 7; i++) { k = i& 3 ; if(i & 4) { k ^= 3; temp0 = R0[k] - R1[k]; .... } else { temp0 = R0[k] + R1[k]; ... } .....(略) } -> 觀察一下原本的內容 , 發現迴圈跑8次要做的事情就是產生
R0[0] + R1[0] ,R0[1] + R1[1] ,R0[2] + R1[2] ,R0[3] + R1[3] ,
R0[3] - R1[3] ,R0[2] - R1[2] ,R0[1] - R1[1] ,R0[0] - R1[0]

-> R0 R1在迴圈之前已經計算好 , 迴圈裡面只要他們之間相加減的數值
於是想說新開一個長度8的一維陣列 , 直接把相加減的數值給放好
如此一來 迴圈裡面的這個部份就可以抽掉

R0[k]+R1[k] / R0[k]-R0[k] 可用SIMD提供的 add / sub函式來完成計算
R0[k]-R0[k] 放入btmp[8]的順序如圖 , 從k=3放回來
計算時的vector是從k=0~3裝入 , 相減的結果要先交換位置才能放入btmp


(3) 數據結果 程式跑10000次 :

1. 原始程式在PPE環境下: 1.48 sec
改寫的程式在PPE環境下: 1.15 sec

2. 原始程式在SPE環境下: 1.28 sec
改寫的程式在SPE環境下: 0.48 sec

-> PPE和SPE都是一樣的程式 , 只是使用的函式不同
因為兩個環境支援的函式名稱是不一樣的 , 但是數據差距有點大
PPE只比原本的少了0.3 , 但SPE少了快三倍

我有請小新學長看一下程式 , 應該沒漏掉或放錯迴圈次數
我們兩個對於PPE為什麼只少0.3 都感到很奇怪

=========== 2009.10.8 ===========

整理了在PPE和SPE下寫的兩個範例
一個是4*4矩陣 , 另一個陣列比大小
範例的寫法也有附上解釋
會和大鈞學長討論哪裡還需要做修改



=========== 2009.09.24 ===========

SIMD程式分為使用VMX指令的PPE和使用SPU SIMD指令的SPE
當初會想用PPE是因為不知道怎樣把SPE裡面的時間傳出來
後來可以把測的時間傳出來 , 於是可以去測SPE提供的指令時間

下午報告的數據 因為迴圈次數給錯 , 導致vec_madd()的時間會較慢
所以我把數據重測了一次 , 結果如下:

(1) 一維陣列相乘


(2) 4*4矩陣相乘


從(1)(2)數據看來 , PPE的vec_madd()函式會比原本節省大約3倍
SPE的spu_mul()函式會比原本節省大約4倍

因為兩種函式都有大幅度的降低時間 , 但是改寫的code效果沒有很好
可能要更改原本程式 , 讓原本的程式能比較適合用在SIMD上


=========== 2009.09.16 ===========

把改寫成SIMD的部分下去測時間 , 時間比較如下:


會發現改寫成SIMD的程式時間 比原本的程式還慢
主要改寫後的程式如下:
原本 : R0[i] += IDCT_Coeff0[k+0] * V0[i];
SIMD : tmp[q] = vec_madd( id_c0[i] , v0[q] , vzero );
R0[i] = Tmp[i] + Tmp[i+1] + Tmp[i+2] + Tmp[i+3] ;

-> 做法是 , 一次讓IDCT_Coeff0[k+0] * V0[i] 的計算做完
把數值存在tmp陣列裡面 , 接著把陣列數值相加再給R0

老師提到 , 把數值給R0[i]用到很多個+ , 可能是這邊導致速度變慢
因為之前沒有實際測過 SIMD支援的函式 是否真的有加速功能
這個禮拜會寫簡單的例子去測時間 .
小新學長說先寫簡單的一維陣列相乘 , 確定SIMD的函式是否有加快
如果有加快 , 再寫矩陣相乘的範例 , 然後去測時間


=========== 2009.08.31 ===========

原本cpp檔需要傳入的參數有7個 , 參照小新學長的意見
除了Mode不是等於0 就是 1 , 其他6個都當成64的一維陣列
這7個參數直接在cpp檔設定 , 一維陣列的數值先隨意給 , 設定如下:
int Mode=0 ;
int BlockLT[64] __attribute__((aligned(16)));
int BlockRT[64] __attribute__((aligned(16)));
int BlockLB[64] __attribute__((aligned(16)));
int BlockRB[64] __attribute__((aligned(16)));
int BlockU[64] __attribute__((aligned(16)));
int BlockV[64] __attribute__((aligned(16)));


在compile時遇到幾個問題或錯誤:
(1) compile時指令的改變
之前寫的範例都是 .c檔 , 這次則是 .cpp檔
所以把指令中的 " gcc " 換成 " g++ " , 這樣就可以了

(2) spu_mul()的語法錯誤
一開始是寫 tmp = spu_mul( id_c0[k], v0) ;
tmp 和 v0這兩個vector所乘載的陣列大小只有4
剛好vector一次就是裝四個 , 以為這樣可以 , 但是compile會有錯誤
後來改成 tmp[q] = spu_mul( id_c0[k] , v0[q] ) ; 變數 q=0
雖然 tmp 和 v0大小只有4 , 但還是要告知vector的起始點

另外 要使用spu_mul() , vector宣告的型態要為float
原本程式V0型態為 int
所以寫成 __vector int *v0 = (__vector int *) V0 ;
compile時會顯示錯誤 , 上網找資料看到都是用float
改成 __vector float *v0 = (__vector float *) V0 ;
這樣執行起來就不會出現錯誤了

測試方面使用SPU SIMD指令的方式
寫了PPE+SPE , SPE裡面就放cpp檔內容
打入compile需要的指令 , 目前不會出現錯誤
但是SPE裡面不能用printf , 這樣無法看到算出來的數字對不對

想說把要印的數值傳到PPE裡 , 執行後印出的數字都是0
可能是要印出的數值沒有傳好 , 或者是數值上有算錯
這邊會想辦法去解決


=========== 2009.08.24 ===========

參考aaa學長提出的兩個方法 , 覺得第二種方法比較簡單
利用這種方法 , 程式碼中原本 d0~d11的變數就可以拿掉
但是第二種方法的問題出在下圖這段程式碼

R0[i] += IDCT_Coeff0[k+0] * V0[0];
R0[i] += IDCT_Coeff0[k+1] * V0[1];
R0[i] += IDCT_Coeff0[k+2] * V0[2];
R0[i] += IDCT_Coeff0[k+3] * V0[3];

--> 這等於把 IDCT_Coeff0陣列和V0陣列相乘的數值都放在R0[i]
SIMD語法中好像沒有這種計算的函式 , 所以不能直接這樣寫


所以把程式碼改寫 如下:

Tmp[i] = IDCT_Coeff0[k+0] * V0[0];
Tmp[i+1] = IDCT_Coeff0[k+1] * V0[1];
Tmp[i+2] = IDCT_Coeff0[k+2] * V0[2];
Tmp[i+3] = IDCT_Coeff0[k+3] * V0[3];

R0[i] = Tmp[i] + Tmp[i+1] + Tmp[i+2] + Tmp[i+3] ;

--> 新開一個tmp[4]陣列,用來暫存 IDCT_Coeff0和V0相乘的數值
把 tmp陣列中四個數值相加後 , 再放回R0[i]
這樣一來 IDCT_Coeff0陣列和V0陣列相乘 的部分就可以一次作

測試的方法: 幫 原本的cpp 和 SIMD化的cpp 各寫PPE+SPE
然後給入一樣的參數數值 , 再去看兩者時間的差別有多少
目前在寫這兩個的PPE+SPE , 但傳入的參數還弄不清楚
所以還無法把程式跑起來



=========== 2009.08.12 ===========


從bbb學長給的mpeg-4檔案中 , 找出要做SIMD的檔案
主要就是改 MacroBlock_DCT_IDCT.cpp
下圖是目前要改成SIMD的地方


(1) 上圖第一個框框的部分, 希望可以用vector去裝變數d0~d11
這樣一次就可以assign 四個變數


(2) 同一個迴圈內, A0=B0+C0 , A1=B1+C1, ..... 這種計算可以改寫
但是 A0=B0+C0 , A1=D1+C1 , A2=B0+C3 ,... 這種不行
所以我把第二個框框的迴圈內容想成下面這樣

希望藉著此種想法 , 讓迴圈內的程式可以改成SIMD化

2009年10月12日 星期一

Special Topic on ESL and Multi-core Tool Design

Syllabus

1. SystemC Simulation Kernel
2. Advanced OpenESL tool development
3. TLM2.X
4. ARM Processor ESL Model
5. Multi-core Virtual Model
6. Multi-core Programming on Virtual Model
7. Multi-core application programming using CUDA
8. Debugging tool for microprocessors

09/23 - 10/07

大鈞陳大鈞_投影片.rar
阿凡EM_for_GMM_on_CUDA.ppt
宗胤8051 SystemC Model.pptx
8051 ISS Implement in SystemC.pptx
品皓gdb_for_8051_品皓.ppt
塞公Memory Locality Exploitation Strategies for FFT on the CUDA Architecture.pptx
rurusystemC kernel.pptx
小聽Course_進度_090923.pptx
Course_進度_090930.pptx
Course_進度_091007.pptx
龍哥Arm9 Cpu.pptx