本記事では、2ステージからなるパイプラインアプリケーションの例でタスク依存関係を使う方法を紹介します。 課題はシンプルなシミュレーションです。平坦な面の中央にオブジェクト P を置き、さらに長方形の箱で取り囲まれているとします。 シミュレーションの各ステップでは、オブジェクトはランダムな方向へランダムな距離だけ移動します。 境界の壁にぶつかったら、初期位置に戻されます。 この課題では、与えられた時間の間で何回4つの壁に当たるかを計算します (Pongゲームとしても知られています)。
図 1. オブジェクト P はランダムに境界の壁にぶつかる
乱数の生成とシミュレーションは並列化できますので、この課題に2ステージパイプラインを使ってみましょう:
- 最初のステージでは擬似乱数ジェネレータを用いて、乱数を生成します。
- 2番目のステージでは、移動のシミュレーションを行います。
ALFでは現在のところパイプラインを直接サポートしていませんので、 パイプライン構造はタスク依存関係を用いてシミュレートされます。 2つのパイプラインステージに2つのタスクを対応させるのです。
今回の課題では、各シミュレーションステップでは動きベクトルのための小さな量のデータしか必要としません。 ALFはどれだけデータが小さくても良いのかについては厳密に定めていませんが、 パフォーマンスの観点からは大きめのデータのほうが好ましいでしょう。 ですので、数千回のシミュレーションステップをグループ化して1つのワークブロックとします。
ステージ1タスクでは、簡単のために、Lagged Fibonacci 擬似乱数ジェネレータ (pseudo-random number generator, PRNG) を使います。 (Lagged Fibonacci 法は疑似乱数ジェネレータの一例で、線形合同法による標準的な方法よりも改善された方法です。 漸化式によって再帰的に定義された Fibonacci (フィボナッチ) 数列の生成に基づいています。 つまり、数列の各項は先行する項の関数として定義されています。)
本例では、Sn=(Sn-j^Sn-k)%232というアルゴリズムを使用しています。
ここでk > n > 0であり、k = 71, j = 65です。
このアルゴリズムでは、過去の値を記憶するために、長さ k の履歴バッファが必要です。
今回の実装では、タスクコンテキストを履歴バッファとして使用します。
入力バッファは必要ないので、このタスクのワークブロックは出力バッファのみを持ちます。
ステージ2タスクでは、シミュレーションのステータスを保持するためにタスクコンテキストを使用します。 ステータスには、オブジェクトの位置、壁に当たった回数が含まれます。 このステージのワークブロックは入力としてステージ1で生成された疑似乱数のみを必要とし、出力はありません。
パイプライン化を行うもう1つの目的は、別々のステージを同時に実行しパフォーマンスの改善を図ることです。 このためには、ステージ間でワークブロックレベルのタスク同期が必要ですが、ALFは今のところサポートしていません。 これに代わるアプローチとして、複数のタスクを使用して、 各タスクはシミュレーション全体の一部分のみを処理するという方法があります。
さて、2ステージタスクができました。 たくさんのワークブロックは、以下のような2つのタスクとして作成します :
- ステージ1タスクは、多数の乱数を生成し、一時バッファに書き出します。
- ステージ2タスクは、一時バッファから乱数を取り出し、シミュレーションを実行します。
ステージ2が正しくステージ1からデータを受け取れるよう、2つのタスクの依存関係をセットしましょう。 PRNGとシミュレーションは両方とも内部状態を必要とするため、 同じステージの次のタスクへ状態データを引き渡し、状態を維持しなければなりません。 ここで説明する方法では、同じステージのタスク同士で同じタスクコンテキスバッファを共有します。 依存関係をセットすることで、タスクが同じタスクコンテキストに正しい順序でアクセスすることを保証します。
図2は、タスク依存関係を表しています。
図 2. ステージ間バッファに個数制限がない場合のタスク依存関係
さらに一時的な中間バッファの使用を削減するために、 ダブルまたはマルチバッファリングの技術を中間バッファに使うこともできます。 図3は、中間バッファにダブルバッファリングを利用した場合のタスク依存関係のグラフです。
図 3. ダブルバッファを使用したタスク依存関係
この例では、前のステージ2タスクがまだ使用しているデータをステージ1タスクが上書きすることが無いように、 n-2番目のステージ2タスクとn番目のステージ1タスクの間に新しい依存関係を追加しています。 この方法がサンプルコードに実装されている方法です。 完全なソースコードは、SDKのサンプルディレクトリの pipe_line をご覧ください。
本記事では、2ステージのパイプラインアプリケーションにおいてALFタスク依存関係を使う方法を紹介しました。
学ぶために
- 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 の技術要約も用意されています。
