IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  Multicore acceleration  >

Let's LTS: 第 1 回 ALF 軽量タスクサポートの概要

ALF の新しい仲間である軽量タスクサポートについて、概要、使い方、そして処理時間に関する簡単な考察を行います

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません


レベル: 中級

土居 意弘 (munepi@jp.ibm.com), IBM Systems & Technology Group, AKD48

2009年 02月 20日

Accelerated Library Framework (ALF) の新しいタスクモデルである、軽量タスクサポート (Lightweight task support, LTS) が SDK 3.1 から加わりました。本記事では、Cell Broadband Engine (Cell/B.E.) のヘテロジニアスマルチコア環境で必要な様々な悩みを一挙に解決してくれる、ALF 軽量タスクサポートの機能と使い方を解説します。

はじめに

Accelerated Library Framework (ALF) の新しいタスクモデルである、軽量タスクサポート (Lightweight task support, LTS) がSDK3.1から加わりました。ALF LTSでは、Cell Broadband Engine (Cell/B.E.) のヘテロジニアスマルチコア環境で必要な様々な定型コードを書かずにすむ、多数の機能を提供しています。各機能と使い方の解説、最後にパフォーマンスの簡単な考察を行います。

概要

ALF LTS を使えば、 Cell/B.E. によるアプリケーション開発には必須の SPE 管理について、書かなければいけない定型コードをぐっと減らすだけでなく、より便利な機能も利用することができます。

ALF LTS の概要について見ていきましょう。

libspe2 を利用した場合

libspe2 を利用して Cell/B.E. のプログラミングを行うためには、少なく見積もっても図 1 に示した処理を行わなければなりません。PPE (メイン)、PPE (SPE管理)、SPEの3つのスレッドを作成し、各スレッドでlibspe2のライブラリ関数の呼び出しやDMA転送、演算処理を行います。この構造は一般的であるためコピー&ペーストで行えるものではありますが、エラー処理を含めて100行程度のコードを準備するのはそれなりに面倒なものでした。


図 1. Cell/B.E.プログラムの一般的な構造
図 1. Cell/B.E.プログラムの一般的な構造

ワークブロックタスクを利用した場合

ALF を使えば、このような定型処理から解放されます。

従来から提供されているタスクモデルであるワークブロックタスク (Work block task) では SPE プログラムを実行するための準備に加えて、並列ジョブのスケジューリングやデータ入出力の DMA 転送までをカバーしており、プログラマがしなければならないのはタスクを並列可能なように分割することと演算処理を書くことだけです。 ALF でカバーされる範囲を図 2 の赤い枠で示しています。

しかし、 DMA 転送やロードバランスなどの高度な処理を提供してくれる一方で、分割したタスクをワークブロックにマップするために書かなければならないコードはそれなりに大きく、新たな定型処理となっていたことは否めません。また、 ALF をフル活用するためにはプログラミングモデルや特性を十分理解しなければならず、これも敷居を高める一因となっていました。


図 2. ALF 及びALF LTSでサポートする範囲
図 2. ALF 及びALF LTSでサポートする範囲

ALF LTS を利用した場合

ALF LTS では、 SPE を実行するまでの部分のみをカバーしており、SPE側で実行される処理についてはほぼすべてプログラマに委ねられています。図 2 の青い枠で示しています。

ALF の特徴であったワークブロックベースの処理を切り捨てて、 DMA 転送も再びプログラマに任せるという割り切りの結果、 ALF LTS を使うために必要なコードも理解しなければならないフレームワークも激減しました。 ALF LTS を使えば libspe2 では 100 行あった定型コードが 30 行ほどで済むようになるだけでなく、 ALF が備えているプログラムの実行時読み込みや切り替え、タスク依存関係を使ったチェーンなどの機能はそのまま利用できるため、気軽に使いやすくなったと言えます。

あらためて ALF LTS の機能をまとめておきます。

機能ALF LTSALF
複数SPEの管理YesYes
SPEプログラムの実行時読み込みYesYes
SPEプログラムの切り替えYesYes
タスク依存関係の設定YesYes
ワークブロックの自動分配NoYes
リダクション処理NoYes



上に戻る


使い方

リスト 1 ~ 4 が ALF LTS を利用した Hello World プログラムになります。SDK 3.1 のサンプルディレクトリ $(CELL_TOP)/src/alf-examples/hello_world_lts/にあるものとほぼ同様ですが、サンプルディレクトリのものはMakefileが特殊であるため、ここでは一般的なものに直してあります。

では、早速 ALF LTS の使い方を見ていきましょう。

ホストのコードを記述する


リスト 1. main.c (PPE 用)

001: #include <stdlib.h>  // for NULL
002: #include <alf.h>     // for alf_xxxx()
003: 
004: int main(int argc, char *argv[])
005: {
006:     alf_handle_t handle;
007:     alf_task_desc_handle_t task_desc_handle;
008:     alf_task_handle_t task_handle;
009: 
010:     alf_init(NULL, &handle);
011:     alf_num_instances_set(handle, 8);
012:     
013:     alf_task_desc_create(handle, 0, &task_desc_handle);
014:     alf_task_desc_set_int32(task_desc_handle,
015:            ALF_TASK_DESC_TASK_TYPE,
016:            ALF_TASK_TYPE_LIGHTWEIGHT);
017:     alf_task_desc_set_int64(task_desc_handle,
018:            ALF_TASK_DESC_ACCEL_LIBRARY_REF_L,
019:            (unsigned long long) "libhello_lts_spu.so");
020:     alf_task_desc_set_int64(task_desc_handle,
021:            ALF_TASK_DESC_ACCEL_IMAGE_REF_L,
022:            (unsigned long long) "hello_lts_spu");
023:     alf_task_desc_set_int64(task_desc_handle,
024:            ALF_TASK_DESC_ACCEL_LTS_MAIN_REF_L,
025:            (unsigned long long) "task_main");
026: 
027:     alf_task_create(task_desc_handle, NULL, 8, 0, 0, &task_handle);
028:     alf_task_finalize(task_handle);
029: 
030:     alf_task_wait(task_handle, -1);
031: 
032:     alf_exit(handle, ALF_EXIT_POLICY_FORCE, 0);
033: 
034:     return 0;
035: }

PPE では主に 5 つの処理を記述する必要があります (リスト 1)。

  1. ALF の初期化と設定 (10 行目、 11 行目)
  2. タスクデクスリプタの作成と内容の設定 (13 行目~ 25 行目)
  3. タスクの作成と実行 (27 行目、 28 行目)
  4. タスク完了の待機 (30 行目)
  5. ALF の終了 (32 行目)

ALF をご存じの方には何も難しいことはありませんね。そうでない方のために、簡単に説明します。

最初は ALF ライブラリ自身の設定です。 ALFを使用する前に alf_init() を呼び出して ALF ハンドルを作成し、 alf_num_instances_set() で使いたいSPE個数の最大値を設定します。

次はタスクの内容を記述するタスクデスクリプタを作成します。本来の ALF には様々な設定があるのですが、 ALF LTS で必要なものはほんの少しです。タスクタイプに ALF_TASK_TYPE_LIGHTWEIGHT を指定すること (14 行目~ 16 行目)、 SPE プログラムが格納されている共有ライブラリ名、実行ファイル名、およびメイン関数の名前を指定すること (17 行目~ 25 行目) のたったこれだけです。

タスクデスクリプタができあがったら、 alf_task_create() でタスクを作成します。 作成された ALF LTS タスクは alf_task_finalize() が呼び出されるまで実行開始を待機しています。ワークブロックタスクではこれらの間にワークブロックの作成などが挟まれますが、 ALF LTS では不要なのですぐに alf_task_finalize() を呼び出しましょう。

タスクの実行を開始したら、 alf_task_wait() で完了を待機します (30 行目)。

最後に alf_exit() を呼び出してリソースを解放しましょう (32 行目)。

アクセラレータのコードを記述する


リスト 2. spu/main_spu.c (SPE 用)

001: #include <stdio.h>
002: #include <alf_accel.h>
003: 
004: int task_main(
005:         void* p_task_ctx,
006:         int instance_id,
007:         int number_of_instance)
008: {
009:     printf("[%s/%s] Hello ALF LTS World !!\n",
010:             instance_id,
011:             number_of_instance);
012:     return 0;
013: }
014: 
015: ALF_ACCEL_EXPORT_API_LIST_BEGIN;
016: ALF_ACCEL_EXPORT_API("", task_main);
017: ALF_ACCEL_EXPORT_API_LIST_END;

SPE のコードもとてもシンプルです (リスト 2)。主に 2 つの部分からなります。

  1. タスクのメイン関数の定義 (4 行目~ 13 行目)
  2. メイン関数のエクスポート宣言 (15 行目~ 17 行目)

ALF LTS を使う場合は、 main() の代わりに、指定の引数を持つ専用の関数を用意する必要があります。ちょうど pthread でスレッド関数を用意することに似ています。関数名も、ここでは task_main() となっていますが、好きな名前に変えて構いません。その場合は、この後に説明するエクスポートの設定と、 タスクデスクリプタの設定も変更する必要があります。

タスクメイン関数の 3 つの引数は順に、タスクコンテキスト、インスタンス ID 、インスタンス総数です。タスクコンテキストは、ホストから与えられる初期データの受け渡しに使いますが、今回は使っていません。インスタンス ID はこのプログラムが実行されている SPE の番号で、number_of_instance 未満の 0 から始まる番号が与えられます。インスタンス総数は同時に実行されているインスタンスの総数を表しています。リスト 1 で alf_num_instances_set() または alf_task_create() の3番目の引数で指定した数値のうち小さい方に等しくなります。

15 行目~ 17 行目では、タスクメイン関数の名前をホストから参照できるよう、エクスポートの設定をしています。作成したメイン関数の名前を正しく指定します。リスト 1 の 25 行目で設定した文字列と一致しなければなりません。

ビルドの方法と必要なライブラリ

リスト 3 はホストプログラムをビルドするための Makefile です。 IMPORTS = -lalf を指定して ALF のライブラリをリンクします。


リスト 3. Makefile (PPE 用)

001: DIRS = spu
002: PROGRAM_ppu = hello_lts
003: IMPORTS = -lalf
004: include $(CELL_TOP)/buildutils/make.footer

リスト 4 はアクセラレータプログラムの Makefile です。 ALF では SPE プログラムを共有ライブラリに含めることになっているので、 SHARED_LIBRARY_embed を指定しています。また、 PROGRAM_spuSHARED_LIBRARY_embed の設定値は、リスト 1 の 22 行目、 19 行目で指定した文字列と一致させなければなりません。

ライブラリのリンクのため、 IMPORTS = -lalflts を指定しています。このライブラリはワークブロックタスク用のものとは異なりますので注意が必要です。


リスト 4. spu/Makefile (SPE 用)

001: PROGRAM_spu = hello_lts_spu
002: SHARED_LIBRARY_embed = libhello_lts_spu.so
003: IMPORTS = -lalflts
004: INSTALL_DIR = ..
005: INSTALL_FILES = $(SHARED_LIBRARY_embed)
006: include $(CELL_TOP)/buildutils/make.footer

実行結果

いよいよプログラムを実行してみましょう。

図 3 のような出力が得られるはずです。最初の 2 つの数字は、 SPE の ID 番号と、総 SPE 数を表しています。 ID 番号の順序は環境によって異なるでしょう。


図 3. hello_lts の実行結果
図 3. hello_lts の実行結果



上に戻る


処理時間

さて、 ALF LTS の世界への挨拶も終わりました。

今後はこれを拡張して DMA 転送や演算処理を実装していくことになりますが、その前に ALF LTS のパフォーマンスを調べてみたいと思います。指定した時間 (INTERVAL) だけ待ってから終了するという SPE ルーチンを作成して、タスクの作成から完了までの時間を計測しましょう。そして、 INTERVAL との差をみれば、 ALF LTS のオーバーヘッドがわかります。

コードの修正

まずホストのプログラムについて、リスト 1 の 27 行目~ 30 行目をリスト 5 に置き換えましょう。 get_usec() は、マイクロ秒単位で時刻を返すなんらかの関数であるとします。タスクを繰り返し実行する場合、使用されていたリソースは自動的に削除されるため、 alf_task_destroy() を呼び出す必要はありません。引き続き新しいタスクを実行したい場合には、すでに作成済みのタスクデスクリプタを使って(あるいは設定を変更して)、再び alf_task_create() を呼び出せば OK です。


リスト 5. 時間計測用の PPE ルーチン

    for (i = 0; i < 100; i++)
    {
        uint32_t st, ed;
        st = get_usec();
        alf_task_create(task_desc_handle, &ctx, option.num_spes, 0, 0, &task_handle);
        alf_task_finalize(task_handle);

        alf_task_wait(task_handle, -1);
        ed = get_usec();
        printf("%u\n", ed - st);
    }

続いてアクセラレータのプログラムです。リスト 2 の 9 行目~ 11 行目をリスト 6 に置き換えましょう。 INTERVAL は待機する時間を表す定数ですが、デクリメンタを使っているため、単位はマイクロ秒ではなくタイムベースの周波数であることに注意してください。たとえば、 QS22 システムでは 266 を指定すれば 10 マイクロ秒待機させることができます。


リスト 6. 時間計測用の SPE ルーチン

    spu_write_decrementer(0xffffffffu);
    while ( 0xffffffffu - spu_read_decrementer() <= INTERVAL );

計測結果の考察

図 4 は、 INTERVAL を 10 マイクロ秒に設定した場合の結果です。タスクの作成と実行を 100 回繰り返して行い、各回の結果を横軸にとっています。縦軸は計測した時間ですが、 10 マイクロ秒から始まっている点に注意してください。 100 マイクロ秒毎に小さな目盛を打ってあります。


図 4. 10 マイクロ秒の処理を連続して実行した場合の総処理時間
図 4. 10 マイクロ秒の処理を連続して実行した場合の総処理時間

このグラフから 2 つのことが読み取れます。 1 つは、タスクの実行毎に 100 マイクロ秒~ 200 マイクロ秒程度のオーバーヘッドがかかること。もう 1 つは、初回の呼び出しだけ非常に大きな時間がかかることです。

SPE プログラムの実行には、ディスクからのプログラム読み込み、 SPE への転送、 SPE の起動などが必要ですが、今回の調査では同じルーチンを繰り返し実行しているため、 2 回目以降はこれらの処理がうまく省略されているものと推測できます。

この数値と傾向は INTERVAL を変化させてもほとんど変わりません (図 5)。


図 5. INTERVAL を 1, 100, 1000, 10000 マイクロ秒にした場合
図 5. INTERVAL を 1, 100, 1000, 10000 マイクロ秒にした場合

次に SPE 個数による実行時間の変化を見てみましょう (図 6)。縦軸は計測した時間で、四角いマーカーは初回を除く 99 回の呼び出しの平均値を、上下に伸びる棒は最大値、最小値の幅を、それぞれ表しています。横軸は SPE の個数です。初回を除いているので、ディスク読み出しやプログラムロードのための転送時間を含まない ALF LTS そのもののオーバーヘッドを示していると言えるでしょう。


図 6. SPE 個数に対する処理時間
図 6. SPE 個数に対する処理時間

このグラフから、 SPE 個数によらず必要な固定部分と、SPE 個数に比例する部分があることがわかります。固定部分が 110 マイクロ秒程度、 比例部分が SPE 1 個あたり 10 マイクロ秒程度といったところでしょうか。また、平均値より上に棒が長く伸びていることから、バラつきの幅がやや大きいことも言えそうです。

先ほどと同様に、 INTERVAL を変化させた場合についても図 7 に示しておきます。


図 7. INTERVAL を 1, 100, 1000, 10000 マイクロ秒にした場合
図 7. INTERVAL を 1, 100, 1000, 10000 マイクロ秒にした場合



上に戻る


次回は

本記事では、 SDK 3.1 で導入された ALF 軽量タスクサポートを使って Cell/B.E. プログラムを書く方法を紹介しました。 ALF LTS を使えば煩わしい定型処理を、とても短いコードで書くことができます。

次回は、紹介しきれなかった ALF LTS の魅力的な機能について、さらに突っ込んで調査していきます。



参考文献

学ぶために
  • ALF については、Fun with ALF シリーズをチェックしましょう。

  • The IBM Semiconductor Solutions Technical Library Power Architecture offerings セクションには、ダウンロードマニュアルや、仕様書などたくさんの有益な情報があります。


製品や技術を入手するために

議論するために


著者について

土居 意弘

土居意弘はIBMで5年間、Cell/B.E. や Digital Signal Processor 上で画像処理システムなどを開発してきました。現在は日本IBMのテクニカルエキスパートとして、 Cell/B.E. 向けソフトウェアの実装やコンサルティング業務などを行っています。




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



 


 


不充分・不完全である大変素晴らしい
 


この記事を共有する

del.icio.us del.icio.us newsing newsing FC2ブックマーク FC2ブックマーク
Choix! Choix! ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
MM/memo MM/memo CZブックマーク CZブックマーク livedoorクリップ livedoorクリップ
はてなブックマーク はてなブックマーク Buzzurl(バザール) Buzzurl(バザール)




上に戻る


IBM, IBMロゴ, Power Architecture、PowerXCellは、International Business Machines Corporationの米国およびその他の国における商標。 Cell Broadband Engine, Cell/B.Eは、米国およびその他の国におけるSony Computer Entertainment, Inc.の商標。 他の会社名、製品名およびサービス名等はそれぞれ各社の商標です。

    日本IBMについて プライバシー お問い合わせ