Cell Broadband Engineを利用したホログラム計算(後編)
3)スレッドとして実行する作業の関数の作成
スレッドとして実行させる作業を関数runSpeThreadとして作成します.spe_context_run関数によりSPEプログラムを実行します〔リスト1(d)〕.
typedef struct{
spe_context_ptr_t speContext; // SPEコンテキスト
DmaParams *dmaParams; // DMA転送用パラメータ
}ThreadArg;
void *runSpeThread(void *arg){
ThreadArg *threadArg = (ThreadArg *) arg;
unsigned int entry; // SPE起動の成功・失敗を保存する変数
spe_stop_info_t speStopInfo;
// SPEが停止した際の情報を格納する変数
entry = SPE_DEFAULT_ENTRY;
spe_context_run(threadArg->speContext,&entry,0,
threadArg->dmaParams,NULL,&speStopInfo);
return NULL;
}
リスト1 PPE用プログラム (d)スレッドとして実行する作業の関数を作成
4)変数の宣言
SPEの実行に用いる変数の宣言を行います〔リスト1(e)〕.
spe_program_handle_t *speProgram;
// SPEプログラム・イメージのハンドル
spe_context_ptr_t speContext[NUM_SPE]; // SPEコンテキスト
int ret;
pthread_t thread[NUM_SPE];
// 生成したスレッドの識別子を格納する変数
threadArg threadArg[NUM_SPE]; // スレッドへの引き数
リスト1 PPE用プログラム (e)変数の宣言
5)SPEプログラムの読み込みとSPEコンテキストの作成
関数spe_image_openにSPEプログラム・ファイルのパスを渡し,SPEプログラム・イメージのオープンを行います.
libspe2では,SPEを「SPEコンテキスト」と呼ばれるオブジェクトに抽象化します.各SPEコンテキストの作成,およびプログラム・イメージのロードを行います.
関数spe_program_loadにSPEコンテキストへのポインタとSPEプログラム・イメージのハンドラへのポインタを渡し,各コンテキストにプログラム・イメージをロードします.
パスfresnel_spe.elfに存在するSPEプログラムをNUM_SPE個のそれぞれのSPEに利用する場合は,リスト1(f)のようにします.
speProgram = spe_image_open("fresnel_spe.elf");
for(i=0;i<NUM_SPE;i++){
speContext[i] = spe_context_create(0,NULL);
spe_program_load(speContext[i],speProgram);
}
リスト1 PPE用プログラム (f)SPEプログラムの読み込みとSPEコンテキストの作成
6)SPEプログラムの各スレッド上における実行
SPEプログラムをスレッド上で実行します.pthread_create関数に生成したスレッドの識別子を格納する変数,スレッド属性を指定するための引き数,スレッドに実行させる作業の関数ポインタ,その関数に渡す引き数を指定し,各SPEでプログラムを実行します〔リスト1(g)〕.
for(i=0;i<NUM_SPE;i++){
threadArg[i].speContext = speContext[i];
threadArg[i].dmaParams = &dmaParams[i];
pthread_create(&thread[i],NULL,runSpeThread,&threadArg[i]);
}
リスト1 PPE用プログラム (g)SPEプログラムを各スレッド上で実行
7)各スレッドの終了待ちとSPEコンテキストの破棄
各スレッドの終了を待ってコンテキストの破棄を行い,SPEプログラムをクローズします.
pthread_join関数に終了を待つスレッドの識別子とスレッドからの戻り値の格納先を渡してスレッド終了を待ち,spe_context_destroy関数に破棄したいSPEコンテキストのポインタを渡して,SPEコンテキストを破棄します.さらに,spe_image_closeに終了したいプログラム・ハンドラへのポインタを渡すことにより,SPEプログラムをクローズします.
NUM_SPE個のスレッドの終了を待ってNUM_SPE個のSPEコンテキストを破棄し,最後にSPEプログラムをクローズするにはリスト1(h)のようにします.
for(i=0;i<NUM_SPE;i++){
pthread_join(thread[i],NULL);
spe_context_destroy(speContext[i]);
}
spe_image_close(speProgram);
リスト1 PPE用プログラム (h)各スレッドの終了を待ち,SPEコンテキストを破棄