|  | レベル: 初級 Kane Scarlett, Editor, Multicore acceleration,
IBM
2008年 04月 29日 今回 Cell Broadband Engine™ (Cell/B.E.) シリーズでは、Accelerated Library Framework (ALF) タスクコンテキストを使って各タスクインスタンスで別々に計算された結果を保存しそれらを統合する方法を学びます。本記事は "ALF for Cell/B.E. Programmer's Guide and API Reference, Version 3.0" (参考資料を参照) を基にしています。
 |
もっと Fun with ALF
Fun with ALF シリーズでもっといろいろなことを学びましょう:
- "Fun with ALF, Part 1: 大きな行列の加算" (developerWorks, March 2008)では、ALFを使って2つの大きな行列を加算する方法を(ホストデータ分割とアクセラレータ分割の例で)説明しています。
- "Fun with ALF, Part 2: I/Oデータの変換"で、16ビットの入力データを8ビットの出力バッファに変換するために、大きなルックアップテーブルとしてタスクコンテキストバッファをどのように使うのかを学びましょう。
- "複数のベクトルの内積 (Multiple vector dot products)"では、タスクコンテキストとバンドルワークブロックを使って、ローカルメモリのサイズ制限のためにワークブロックが分割されたデータを保持できない状況への対処法を明らかにします。
- "オーバーラップI/Oバッファ (Overlapped I/O buffer)"では、オーバーラップI/Oバッファを行列の加算に使用する方法について調べています。
- "タスク依存関係 (Task dependency)"では、2つのステージを持つパイプラインアプリケーションを題材にタスクの依存関係を使う簡単なシミュレーションを行います。
そして、Cell/B.E.プログラミングを簡単にしてくれる、DaCS, BLASそしてその他の技術に注目したFun withシリーズも見てみましょう。
|
|
はじめに
本記事では、ALF タスクコンテキストを使って各タスクインスタンスで別々に計算された結果を保存し、それらを統合して最終結果を作る方法を学びます。
この例では、大きなデータセットから最小値と最大値を探索します。逐次コードはとてもシンプルな教科書通りの実装になります。データセット全体に渡って比較と最良の値の更新を繰り返す線形探索のコードです。
ALFフレームワークを使えばこの逐次コードを並列アルゴリズムに変換することができます。まずデータセットを小さなワークブロックに分割します。そして各ワークブロックはアクセラレータで実行中の各タスクインスタンスに割り当てられます。各タスクインスタンスの計算カーネルが呼び出されて、割り当てられたワークブロックから最大値または最小値を探します。全てのワークブロックが処理された時点で、複数の最大値/最小値候補が各タスクインスタンスのコンテキストに格納されています。それから、ALFランタイムはアクセラレータ上のコンテキストマージ関数を実行し、中間結果のリダクション処理を行って最終結果を生成します。
図 1. 最小値/最大値探索の仕組み
図 1 は最小値/最大値探索プログラムがどのように動くかを表しています。サンプルコードはsampleディレクトリのtask_context/min_maxにあります。より複雑な応用を作る場合にもこのサンプルをテンプレートとして使うことができるでしょう。
計算カーネルのコーディング
次は計算カーネルのコードセクションです。計算カーネルは与えられた入力バッファから最大値と最小値を探し、task_contextをそれらの値で更新します。
/* ---------------------------------------------- */
/* アクセラレータ側のコード */
/* ---------------------------------------------- */
/* 計算カーネル関数 */
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_int32_t *a = (alf_data_int32_t *)p_input_buffer;
unsigned int size = p_parm->num_data;
unsigned int i;
/* 最良の値をコンテキストバッファへ格納する */
for(i=0;i<size;i++) {
if(a[i]>p_ctx->max)
p_ctx->max = a[i];
else if(a[i]<p_ctx->min)
p_ctx->min = a[i];
}
return 0;
}
|
値のマージ
次のコードはcontext_merge関数です。ALFランタイムは、すべてのタスクインスタンスがすべてのワークブロックの処理を終えたのち、自動的にこの関数を呼び出します。タスクインスタンスがこの関数を使ってマージされ、最終的な最小値/最大値がタスクコンテキストに格納されます。
/* コンテキストマージ関数 */
int ctx_merge(void* p_task_context_to_be_merged,
void* p_task_context)
{
my_task_context_t *p_ctx = (my_task_context_t *) p_task_context;
my_task_context_t *p_mgr_ctx = (my_task_context_t *)
p_task_context_to_be_merged;
if(p_mgr_ctx->max > p_ctx->max)
p_ctx->max = p_mgr_ctx->max;
if(p_mgr_ctx->min < p_ctx->min)
p_ctx->min = p_mgr_ctx->min;
return 0;
}
|
まとめ
今回はALF タスクコンテキストを使って各タスクインスタンスの部分的な計算結果を保持し、それらを統合して最終結果を生成する方法を学びました。
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Kane Scarlett は技術ジャーナリスト/アナリストとして20年の経験があり、National Geographic, Population Reference Bureau, Miller Freeman, IDGで記事を書いています。また、恐れ多くも各種のジャーナル誌、JavaWorld、LinuxWorld、そしてもちろんdeveloperWorksへの記事の管理、編集、執筆を行っています。 |
記事の評価
|  |
この記事は、土居 意弘 (munepi@jp.ibm.com) (IBM Systems & Technology Group, AKD48) が翻訳しました。 IBM, IBMロゴ, Power Architecture、PowerXCellは、International Business Machines Corporationの米国およびその他の国における商標。 Cell Broadband Engine, Cell/B.Eは、米国およびその他の国におけるSony Computer Entertainment, Inc.の商標。 他の会社名、製品名およびサービス名等はそれぞれ各社の商標です。 |