 | レベル: 初級 Kane Scarlett, Editor, Multicore acceleration,
IBM
2008年 03月 25日 今回のCell Broadband Engine(TM) (Cell/B.E.) シリーズでは、16ビットの入力データを8ビットの出力データへ変換する例を通じて、Accelerated Library Framework (ALF) のタスクコンテキストバッファを大きなルックアップテーブルとして使う方法を学びます。本記事は "ALF for Cell/B.E. Programmer's Guide and API Reference, Version 3.0" (参考資料を参照) を基にしています。
Introduction
本記事では、16ビットの入力データを8ビットの出力データへ変換する例を通じて、Accelerated Library Framework (ALF) のタスクコンテキストバッファを大きなルックアップテーブルとして使う方法を学びます。ルックアップテーブルは65536個の要素を持ち、次のように定義されています。
 |
もっと Fun with ALF
Fun
with ALF シリーズでもっといろいろなことを見つけましょう:
- このシリーズの第一回目、"Fun with ALF, Part 1: 大きな行列の加算"
(developerWorks, March 2008)では、ALFを使って2つの大きな行列を加算する方法を(ホストデータ分割とアクセラレータ分割の例で)説明しています。
- "Min-max 探索 (Min-max finder)"では、タスクコンテキストを使って、各タスクインスタンスの部分の計算結果を保持し、これらの部分結果を併せて最終結果を得る方法を学びます。
- "複数のベクトルの内積 (Multiple vector dot products)"では、タスクコンテキストとバンドルワークブロックを使って、ローカルメモリのサイズ制限のためにワークブロックが分割されたデータを保持できない状況への対処法を明らかにします。
- "オーバーラップI/Oバッファ (Overlapped I/O buffer)"では、オーバーラップI/Oバッファを行列の加算に使用する方法について調べています。
- "タスク依存関係 (Task dependency)"では、2つのステージを持つパイプラインアプリケーションを題材にタスクの依存関係を使う簡単なシミュレーションを行います。
そして、Cell/B.E.プログラミングを簡単にしてくれる、DaCS, BLASそしてその他の技術に注目したFun withシリーズも見てみましょう。
|
|
For all -32768 <= in <32768
/ 0, in < -4096
Table(n)=| in/32 -4096 <=in<4096
\ 255, in >= 4096
|
次以降のセクションでは、必要最小限に絞ったコードを提示しています。あまり面白みのないルーチンは削除してあり、カギとなる特徴的な部分のみに焦点があてられるようになっています。ホストコードはタスクコンテキストバッファ(ルックアップテーブル)を既に初期化しておりまたテーブルは読み込み専用データとして使われるので、コンテキストセットアップ関数およびコンテキストマージ関数をアクセラレーション側に用意する必要はありません。
このサンプルは、もっと複雑なアプリケーションを作るためのテンプレートとして使うことができるでしょう。
ホストとアクセラレータでの共有するデータ構造についての検討
次のコード片は、ホストとアクセラレータが共有するデータの構造体です。my_task_context_t データ構造体は、ルックアップテーブルを格納します。my_wb_parms_t データ構造体は各ワークブロックに対するパラメータとコンテキストデータとして使われます。
/* ---------------------------------------------- */
/* ホストとアクセラレータで共有されるデータ構造体 */
/* ---------------------------------------------- */
typedef struct _my_task_context_t
{
alf_data_byte_t table[65536];
} my_task_context_t;
typedef struct _my_wb_parms_t
{
alf_data_uint32_t num_data; /* number of data in this WB */
} my_wb_parms_t;
|
タスクデスクリプタのセットアップ
次は、このアプリケーションでタスクデスクリプタをどのようにセットアップしているかのコード片です。タスクコンテキストに関連した情報はコード中に太字フォントで示してあります。
alf_task_desc_create(alf_handle, 0, &task_desc_handle;);
/* タスクデスクリプタのセットアップ */
/* 計算カーネルの名前 */
alf_task_desc_set_int64(task_desc_handle,
ALF_TASK_DESC_ACCEL_KERNEL_REF_L, "comp_kernel");
/* タスクコンテキストバッファーのサイズ */
alf_task_desc_set_int32(task_desc_handle,
ALF_TASK_DESC_TSK_CTX_SIZE, sizeof(my_task_context_t));
/* ワークブロックパラメータバッファーのサイズ */
alf_task_desc_set_int32(task_desc_handle,
ALF_TASK_DESC_WB_PARM_CTX_BUF_SIZE, sizeof(my_wb_parms_t));
/* 入力バッファーのサイズ */
alf_task_desc_set_int32(task_desc_handle,
ALF_TASK_DESC_WB_IN_BUF_SIZE,
PART_SIZE*sizeof(alf_data_int16_t));
/* 出力バッファーのサイズ */
alf_task_desc_set_int32(task_desc_handle,
ALF_TASK_DESC_WB_OUT_BUF_SIZE,
PART_SIZE*sizeof(alf_data_byte_t));
/* タスクコンテキストエントリー */
alf_task_desc_ctx_entry_add(task_desc_handle, ALF_DATA_BYTE,
sizeof(my_task_context_t)/sizeof(alf_data_byte_t));
|
ワークブロックのセットアップ
次はワークブロックを作成するコードを見てみましょう。
/* ワークブロックの作成と、パラメータとI/Oバッファの追加 */
for (i = 0; i < NUM_DATA; i += PART_SIZE)
{
alf_wb_create(task_handle, ALF_WB_SINGLE, 0, &wb_handle);
alf_wb_dtl_begin(wb_handle, ALF_BUF_IN, 0); /* 入力 (input) */
alf_wb_dtl_entry_add(wb_handle, pcm16_in+i, PART_SIZE, ALF_DATA_INT16);
alf_wb_dtl_end(wb_handle);
alf_wb_dtl_begin(wb_handle, ALF_BUF_OUT, 0); /* 出力 (output) */
alf_wb_dtl_entry_add(wb_handle, pcm8_out+i,PART_SIZE, ALF_DATA_BYTE);
alf_wb_dtl_end(wb_handle);
wb_parm.num_data = PART_SIZE;
alf_wb_parm_add(wb_handle, (void *)&wb_parm, /* ワークブロックパラメータ (wb parm) */
sizeof(wb_parm)/sizeof(unsigned int), ALF_DATA_INT32, 0);
alf_wb_enqueue(wb_handle);
}
|
アクセラレータのコードの作成
次はアクセラレータ側のコードです。タスクコンテキストを変更しているコード部分は太字で示しています。
/* ---------------------------------------------- */
/* アクセラレータ側のコード */
/* ---------------------------------------------- */
/* 計算カーネル関数 */
int comp_kernel(void *p_task_context, void *p_parm_ctx_buffer,
void *p_input_buffer, void *p_output_buffer,
void *p_inout_buffer,
unsigned int current_count, unsigned int total_count)
{
my_task_context_t *p_ctx = (my_task_context_t *) p_task_context;
my_wb_parms_t *p_parm = (my_wb_parms_t *) p_parm_ctx_buffer;
alf_data_int16_t *in = (alf_data_int16_t *)p_input_buffer;
alf_data_byte_t *out = (alf_data_byte_t *)p_output_buffer;
unsigned int size = p_parm->num_data;
unsigned int i;
// 実にシンプルなテーブルルックアップ
for(i=0;i<size;i++)
{
out[i] = p_ctx->table[(unsigned short)in[i]];
}
return 0;
}
|
まとめ
完了です!16ビットの入力データを8ビットの出力データへ変換するために、ALFのタスクコンテキストバッファを大きなルックアップテーブルとして使うのは難しくありませんね。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Kane Scarlett は技術ジャーナリスト/アナリストとして20年の経験があり、National Geographic, Population Reference Bureau, Miller Freeman, IDGで記事を書いています。また、恐れ多くも各種のジャーナル誌、JavaWorld、LinuxWorld、そしてもちろんdeveloperWorksへの記事の管理、編集、執筆を行っています。 |
記事の評価
|  |