オーバーラップI/Oバッファとは、入力と出力両方のデータを含んだワークブロックのバッファです。入力と出力の区分けは各ワークブロックに対して動的に指定されます。 このバッファはアクセラレータのメモリを最大限使いたい場合や入力バッファを出力データで上書きしてもよい場合に特に有効です。
入力バッファに転送されるデータは、ホストメモリ内の大きなデータセットのバラバラの区域から転送されて、アクセラレータの入力バッファに集められることがあります (訳注:ギャザー転送のこと)。 ALFフレームワークは入力データの不要な複製を避けることでパフォーマンス上のオーバーヘッドを最小化しています。
出力バッファは、単一の連続したアクセラレータ上のメモリです。
出力データはホストメモリ上の大きな出力バッファのバラバラの区域に転送されることがあります (訳注:スキャッター転送のこと)。計算カーネルが1つのワークブロックの処理を終えた後、出力バッファ内のデータはワークブロックが作成された時にalf_wb_dtl_entry_addルーチンで指定されたホストメモリ内の位置へ移動されます。
次の2つのシンプルな例で、オーバーラップI/Oの使い方を見てみましょう。 どちらも行列の加算の例です。
- 実装 1 C = A + Bを実装します。A, B, およびC は異なる行列です。ホストには3つの領域a,b,cが別々に確保されています (図 1)。
図 1. オーバーラップI/Oを利用した C = A + B の実装
- 実装 2 A = A + Bを実装します。行列Aは、計算結果で上書きされます。領域aおよび領域bがホストに用意されており、a + bの結果はaに格納されます (図 2)。
図 2. オーバーラップ I/O バッファを利用した A = A + B の実装
このコードはFun with ALF: 第 1 回 大きな行列の加算のmatrix_add の例とよく似ています。関連部分のみリスト1に示します。
リスト 1. 行列のセットアップ
/* ---------------------------------------------- */
/* matrix declaration for the two cases */
/* ---------------------------------------------- */
#ifdef C_A_B // C = A + B
alf_data_int32_t mat_a[ROW_SIZE][COL_SIZE]; // the matrix a
alf_data_int32_t mat_b[ROW_SIZE][COL_SIZE]; // the matrix b
alf_data_int32_t mat_c[ROW_SIZE][COL_SIZE]; // the matrix c
#else // A = A + B
alf_data_int32_t mat_a[ROW_SIZE][COL_SIZE]; // the matrix a
alf_data_int32_t mat_b[ROW_SIZE][COL_SIZE]; // the matrix b
#endif
|
リスト2では2つの場合でワークブロックを作成する流れについて示しています。
リスト 2. ワークブロックの作成
for (i = 0; i < ROW_SIZE; i+=PART_SIZE){
if(i+PART_SIZE <= ROW_SIZE)
wb_parm.num_data = PART_SIZE;
else
wb_parm.num_data = ROW_SIZE - i;
alf_wb_create(task_handle, ALF_WB_SINGLE, 0, &wb_handle);
#ifdef C_A_B // C = A + B
// 入力データ A, B
alf_wb_dtl_begin(wb_handle, ALF_BUF_OVL_IN, 0); // オフセットは 0
alf_wb_dtl_entry_add(wb_handle, &mat_a[i][0], wb_parm.num_data*COL_SIZE,
ALF_DATA_INT32); // A
alf_wb_dtl_entry_add(wb_handle, &mat_b[i][0], wb_parm.num_data*COL_SIZE,
ALF_DATA_INT32); // B
alf_wb_dtl_end(wb_handle);
// 出力データ C は、入力データ A と同じ領域
// オフセットは 0 、つまり入力データ A と同じ領域
alf_wb_dtl_begin(wb_handle, ALF_BUF_OVL_OUT, 0);
alf_wb_dtl_entry_add(wb_handle, &mat_c[i][0], wb_parm.num_data*COL_SIZE,
ALF_DATA_INT32); // C
alf_wb_dtl_end(wb_handle);
#else // A = A + B
// 入力および出力データ A
alf_wb_dtl_begin(wb_handle, ALF_BUF_OVL_INOUT, 0); // offset 0
alf_wb_dtl_entry_add(wb_handle, &mat_a[i][0], wb_parm.num_data*COL_SIZE,
ALF_DATA_INT32); // A
alf_wb_dtl_end(wb_handle);
// 入力データ B は、A の後ろに配置する
alf_wb_dtl_begin(wb_handle, ALF_BUF_OVL_IN,
wb_parm.num_data*COL_SIZE*sizeof(alf_data_int32_t));
alf_wb_dtl_entry_add(wb_handle, &mat_b[i][0], wb_parm.num_data*COL_SIZE,
ALF_DATA_INT32); // B
alf_wb_dtl_end(wb_handle);
#endif
alf_wb_parm_add(wb_handle, (void *)&wb_parm, sizeof(wb_parm)/sizeof(unsigned int),
ALF_DATA_INT32, 0);
alf_wb_enqueue(wb_handle);
}
|
リスト3はアクセラレータのコードです。どちらの場合でも出力用のscは、saおよびsbと同じアクセラレータのメモリにセットされています。
リスト 3. サンプルコード
/* ---------------------------------------------- */
/* the accelerator side code */
/* ---------------------------------------------- */
/* the computation kernel function */
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)
{
unsigned int i, cnt;
int *sa, *sb, *sc;
my_wb_parms_t *p_parm = (my_wb_parms_t *) p_parm_context;
cnt = p_parm->num_data * COL_SIZE;
sa = (int *) p_inout_buffer;
sb = sa + cnt;
sc = sa;
for (i = 0; i < cnt; i ++)
sc[i] = sa[i] + sb[i];
return 0;
}
|
本記事では、オーバーラップI/Oバッファを使って行列の加算を行う2つの例を紹介しました。
学ぶために
- RSS feedを使って、このシリーズの更新をチェックしましょう(developerWorks Japan RSS フィードについてはこちら)。
- 本記事で解説されている内容の原文はAccelerated Library Framework for Cell Broadband Engine Programmer's Guide and API Referenceを参照してください。
- Fun with ALF シリーズの他の記事もチェックしましょう。
- 手軽に読める他のALF関連ガイドも見てみましょう:
- "Introducing ALF"
- "10 major ALF concepts"
- "Programming with ALF: Basic ALF application structure."
- "Programming with ALF: Double buffering"
- "Programming with ALF: Handling ALF constraints"
- "Programming with ALF: Optimizing ALF applications"
- "ALF and hybrid x86"
- もっとCell/B.E.プログラミングを学ぶには、次のdeveloperWorksシリーズに挑戦しましょう:
- "Programming high-performance applications on the Cell/B.E. processor"
- "PS3 fab-to-lab"
- "The little broadband engine that could"
- The IBM Semiconductor Solutions Technical Library のCell Broadband Engine documentation セクションには、ダウンロードマニュアルや、仕様書などたくさんの有益な情報があります。
- developerWorks ニュースレターに登録すると、最新の開発者向けニュースと Cell/B.E.に関する最新情報を毎週メールで受け取れます。ニュースレターで Cell/B.E.関連のニュースを受信するには、登録する際にPower Architecture® にチェック・マークを付けてください。
製品や技術を入手するために
- 全ての Cell/B.E.関連記事、ディスカッションフォーラム、ダウンロードなどは IBM developerWorks の Cell Broadband Engine resource center にあります。
- Cell/B.E.カスタム製品やカスタムプロセッサを用いたソリューションのお問い合わせはこちら: Contact us about Cell Broadband Engine technology。
- IBM SDK for Multicore Acceleration 3.0を入手しましょう。また、Cell/B.E.資料のライブラリーにも情報が網羅されています。
議論するために
- ディスカッション・フォーラムに参加してください。
- 質問はIBM developerWorks Power Architecture Cell Broadband Engine discussion forum へ投稿してください。フォーラムに投稿された興味深い問題と答えは、定期的に集められたこちらの"Forum watch" ブログシリーズでハイライトされています。
- Cell Broadband Engine/Power Architecture ブログにアクセスして、Cell/B.E.やその他の Power Architecture 関連技術に関するニュース、ダウンロード、資料、イベント通知を参照してください。人気の高い"Forum watch"ブログ・シリーズ (Q&A 要約) と"FixIt"技術更新情報、それに Infobomb の技術要約も用意されています。
