2009年10月29日 星期四

Cell Programming Tool - ㄚ凡

====================== 09.10.29 ======================

現在傳值的部分OK了
就是PPE裡給他一個array
讓它經過各個SPE運算
最後傳回PPE做輸出
現在開始寫API的說明跟整個tool的介紹
還要把codegen改好

====================== 09.10.15 ======================

目前
「PPE傳給SPE一個陣列
然後陣列在SPE之間計算傳遞
最後再傳回給PPE輸出」
已經OK了

之前因為系統只回傳一個 SPE_RUNTIME_EXCEPTION
只能一行一行註解來找 到底問題在哪
後來發現是在SPE收到PPE傳來的東西後
要更新read address時出的問題

因為大家的address丟來丟去
有時候是Local Storage的位址
有時候是effective address
沒轉換好 記憶體就會有問題

現在PPE可以傳東西給SPE
可是因為無法更新read address 所以只能傳一次
只要找出來read address是在哪裡算錯 就能解決了

接下來看Queue的相關函式能不能合併一下
測試一下大一點的陣列傳遞
就能根據這些程式碼來改codegen了

====================== 09.09.16 ======================

先說一下Double Buffer
學長提到的non-blocking DMA
是不是要問這兩個spe之間的同步機制

對每2個frame來說
spe1 :
    wait_dma_complete(TAG10);
        <IMC的動作>
    FE_enqueue(&MyFrame, TAG10, &P_PPE);
    OutputSel = (++nFrameCount)&0x1;
        <PB的動作>

spe2 :
        <PB的動作>
    OutputSel = (++nFrameCount)&0x1;
    wait_dma_complete(TAG10);
        <IMC的動作>
    FE_enqueue(&MyFrame, TAG10, &P_PPE);

利用 wait_dma_complete(TAG10); 這個函式
來作waiting,直到上一筆傳輸確定做完

在呼叫 FE_enqueue(&MyFrame, TAG10, &P_PPE);
將這一個frame的運算結果傳回PPE時
不用等到傳輸結束
就可以先開始進行
下一個frame的PB運算

--

上禮拜說要寫個例子
因為還沒寫完 所以這禮拜也沒辦法報

====================== 09.09.08 ======================


目前Queue SPE->PPE的function改好了 也測試過了
Queue PPE->SPE的部分寫出來了 可是還沒測過
接下來想寫一個簡單的例子
把資料從PPE傳進SPE 算完後傳回PPE 輸出
等到這部分完成後 再來改codgen的部分

下面來個示意圖 說明一下不同Queue的初始化
方形的框是SPE
SPE旁邊長的兩個小框 上面是in_mbox 下面是out_mbox
圓的是PPE
然後箭頭則是初始化的步驟 (綠色是consumer 紅色是producer)
1. Consumer送 queue address
2. Producer拿 queue address
3. Producer送 read address
4. Consumer拿 read address


由上而下分別表示SPE->SPE、SPE->PPE、PPE->SPE
三種初始化傳位址方式
(這邊寫得比較簡化 實際上queue address是放在MAIL MESSAGE中
再把MAIL address 傳到producer那邊
而read address就直接傳給consumer 不透過MAIL MESSAGE)

====================== 09.09.01 ======================

Queue的重點主要在初始化的部分
需要經過4個步驟
1. Consumer送 queue address
2. Producer拿 queue address
3. Producer送 read address
4. Consumer拿 read address

目前spe之間的queue初始化
都是把address寫入對方spe的in_mbox
而ppe與spe之間的queue初始化所需的溝通
則是利用spe的in_mbox與out_mbox來完成

這邊舉例說明一下
假設spe1為producer spe2為consumer
spe2要將queue address 傳給spe1 :
首先spe2把要傳的queue address放進MAIL (傳遞用的資料型態)
再把MAIL address用mfc_put放入spe1的in_mbox中
接著spe1從自己的in_mbox中讀出MAIL address
再用mfc_get從這個位址取得MAIL
再從MAIL裡拿出queue address

只是PPE在扮演producer或consumer時
照這樣寫 又得多出8個類似的function
我想把它們盡量簡化 不然queue的初始化會非常複雜

接下來是資料的input
目前input是在module裡
也就是data flow中第一個執行的module若是VLD
就在VLD的function裡 取得bitstream
只有在運算完成 在data flow中最後一個module
負責把output送回ppe 由ppe來播放
這樣的流程不知道需不需要更動

另外 在學長的code中 spe1與spe2有使用double buffer
由這兩個spe輪流作輸出
我還看不太懂為什麼這樣實作
不過 我們的tool裡應該不用實作這部分吧

====================== 09.08.18 ======================

關於學長的程式
整個結構跟流程懂了
至於每個部分的實作細節
(由xml經過schedular來決定每個spe要放哪些module)
現在是有概念 但沒有說每一行都仔細看過
大致上是不需要改動的
不過學長當時有跟我說一些小地方 還有討論的空間
(都在schedular裡)
這些地方需不需要修改 等我codegen改的差不多了再決定

Queue的使用也知道了
實作上還有點看不懂 為什麼要這樣做
(會這樣寫一定有特定的理由 我還得再想想)
在queue的初始化部分
看懂了 可是覺得有點不直觀 可能會稍作修改

另外 因為是要open給人家用的
所以產生的程式碼必須加一些註解
至少讓使用者知道每一段程式碼分別在作什麼

queue的實作部分目前只有spe之間
接下來得寫出ppe用的版本
(memory access的function不同)

====================== 09.07.29 ======================

昨天請教學長之後知道

要透過schdular來安排資料在spe之間的流向
所以我們可以幫使用者做好資料傳輸的部分
使用者只需要填入他所要傳的資料當參數即可

所要產生的程式碼包含 :
ppe用的程式碼,負責初始化spe及餵資料
最後的輸出動作等
spe用的程式碼,由於我們已經知道資料的流向,使用者只須負責每個module內部的運算部分

至於傳輸資料的實作部分,我還有一些問題需要釐清,待明天跟學長討論之後再上來說

====================== 09.07.28 ======================

這篇討論串的目的是希望能開發一個generalize的tool
以便使用者在Cell上開發自己的程式

本來希望能將之前的圖形介面改寫成更一般化
能藉由拉進一個個module
再指定module之間要使用的傳輸方式
產生code 使用者只需要自己補完程式中運算的部分
ppe與spe、spe與spe之間的傳輸由我們的tool來產生

不過 之前的GUI是針對schedular設計
只需要指定module間的資料流向
程式碼的產生由schedular負責

而現在我們所要產生的code不包含程式的運算部分
也就是module要在何時將資料送到下一個module
而且傳多大的資料 我們並不知道
只能提供一個預先定義好的function 供使用者傳輸資料用
這麼做的話
我們似乎就不需要去考慮使用者有幾個module
以及這幾個module之間的資料流向
我們能提供的只有ppe及spe的程式碼範本
以及一個可簡單使用的傳輸資料function

之前師公所寫的codegen已可產生所需的程式碼
至於傳輸資料的function 我想使用之前學長寫的queue
稍加包裝應該就能供一般使用者用了
而要怎麼加入GUI 怎麼讓使用者能簡單的開發自己的程式
我還要在跟老師討論一下

10 則留言:

SCREAMLab 提到...

弄清楚double buffer在MPEG-4 coder裡的作用了嗎?

alandai 提到...

我有在學長的論文還是之前的投影片裡看過 知道理論
實作起來好像是兩個spe每做一個frame就交換一次身分
變成這兩個spe輪流在做計算以及輸出的動作
用這樣的方式來節省傳輸時間

Zhong-Ho Chen 提到...

我記得double buffer 應該是 non-blocking DMA

bbb 提到...

我已經回你的mail, 請收信 :)

逼逼逼 提到...

這樣想可能容易轉不太過來,以資料每筆的傳輸當做一個單位,應該不要有frame的想法。

Double Buffer的機制

// Do Task1
// Send nonBlocking-DMA-tag1 (var1)

// Do Task2
// Send nonBlocking-DMA-tag2 (var2)

// Do Task3
// wiat DMA-tag1 complete
// using memcpy(var1,xxx);
// send nonBlocking-DMA-tag1 (var1)

因為我們要結省掉memcpy的時間,
所以提前check DMA-tag1已經完成了沒,以方便直接使用var1。
所以進化成

// wiat DMA-tag1 complete (var1)
// Do Task3
// send nonBlocking-DMA-tag1 (var1)

SCREAMLab 提到...

照這樣做, 速度上有多大的優勢可以看出來嗎?

感謝bbb! 品皓那邊請你也多幫忙!

上班這麼多天了, 我也讀了你的信, 最近有改變一點嗎? 少病少惱了嗎?

匿名 提到...

您好,請問您一下
我現在身邊有一台ps3 裡面以灌好fedora 9
也有抓了CELLSDK-Devel-Fedora_3.1.0.0.0.0.iso和Extra-Fedora_3.1.0.0.0.0還有cell-installer-3.1-0.0.noarch.rpm

請問我該如何開始呢??

另外,我看了devel和extra裡面怎麼都有cell-installer-3.1-0.0.noarch.rpm
這三個rpm都一是一樣的嗎?

最後,是不是有ps3就可以直接寫cell code開發,不用再裝模擬器

謝謝感恩

SCREAMLab 提到...

大鈞,這一串以後由你管,可以嗎?

請找一下BBB與雙魚一起合作,趕快把書的內容寫出來。寫好的部分貼在此。

逼逼逼 提到...

@匿名
Hi Sir,
You can install the Yellow Dog Linux on the Cell Broadband Engine(PS3). You just install this OS, after that, you can write the program as usual on the linux.

If you have any problems, please let me know. I will glad to answer your question.

@SCREAM Lab
Dear my teacher,
I remember the problem we discussed before, we will open this book in my blog. Has anything changed?
Although I really have no time to do this job, but you know... I have this idea in my mind :p
If something was changed, please let me know. I will respect your descision. :)

柯基 提到...

Hello 逼逼逼
我最近遇到一個cell programming的問題

我利用spe_context_create去開啟1個spe和6個spe作運算時間比較,並印出結果
create_one_spe:
//ppe.c
#include
#include
#include

extern spe_program_handle_t spu;

int main(int argc,char *argv)
{
int i;
spe_context_ptr_t spe;
unsigned int entry_point;
int retval;
spe_stop_info_t stop_info;

spe = spe_context_create(0,NULL);
if(!spe)
{
perror("spe_context_create");
exit(1);
}

retval = spe_program_load(spe,&spu);
if(retval)
{
perror("spe_program_load");
exit(1);
}

entry_point = SPE_DEFAULT_ENTRY;
retval = spe_context_run(spe,&entry_point,0,NULL,NULL,&stop_info);
if(retval < 0)
{
perror("spe_context_run");
exit(1);
}

retval = spe_context_destroy(spe);
if(retval)
{
perror("spe_context_destroy");
exit(1);
}
return 0;
}

//spe.c
#include
int main()
{
int a[4] = {1,2,3,4};
int b[4] = {1,2,3,4};
unsigned long long int c[4] = {0};
int i=0;
int j=0;
for(j=0;j<100000000;j++)
{
for(i=0;i<4;i++)
{
c[i] = a[i] * b[i];
}
}
for(i=0;i<4;i++)
{
printf("c[%d] = %lld\n",i,c[i]);
}
return 0;
}
=====================================
create_six_spe:
//ppe.c
#include
#include
#include
#include

typedef struct ppu_pthread_data{
spe_context_ptr_t speid;
pthread_t pthread;
void* argp;
}ppu_pthread_data_t;

void *ppu_pthread_function(void *arg){
ppu_pthread_data_t*data = (ppu_pthread_data_t*)arg;
int retval;
unsigned int entry = SPE_DEFAULT_ENTRY;
if((retval=spe_context_run(data->speid,&entry,0,data->argp,NULL,NULL))<0){
perror("spe_context_run");
exit(1);
}
pthread_exit(NULL);
}

extern spe_program_handle_t spu;
ppu_pthread_data_t data[16];

int main(int argc,char **argv){
int i,retval,spus;
spus = spe_cpu_info_get(SPE_COUNT_USABLE_SPES,0);

printf("%d\n",spus);

for(i=0;i

int main()
{

int a[4] = {1,2,3,4};
int b[4] = {1,2,3,4};
unsigned long long int c[4] = {0};
int i=0;
int j=0;
for(j=0;j<100000000;j++)
{
for(i=0;i<4;i++)
{
c[i] = a[i] * b[i];
}
}

for(i=0;i<4;i++)
{
printf("c[%d] = %lld\n",i,c[i]);
}
return 0;
}

我發現到不管是開啟一個spe也好還是6個spe,執行時間是一樣的,似乎沒有平行運算?
我想請問問體是發生在?
謝謝

另外逼逼逼我可以跟你要一下信箱嗎?
感恩