本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

Cell プログラミングおさらい: Hello World again

これまで掲載してきましたCellプログラミング手法のおさらいシリーズです。初めての方もどうぞ!

森 由美 (morip@jp.ibm.com), 日本アイ・ビー・エム(株)Systems & Technology Group
森 由美の肖像写真
著者は日本アイ・ビー・エムで数年にわたって画像処理検査装置などのソリューション開発を行ってきました。本記事をとおして少しでもみなさまのお役に立てればと思います。最近は国際宇宙ステーションが見える日をチェックしては朝焼け前の星空を眺めて宇宙のロマンにひたっています。(森由美 日本アイ・ビー・エム(株)ハイブリッドシステム開発に所属、工学博士)

概要: IBMが開催しましたCell Broadband Engine (Cell/B.E.)プログラミング初級セミナーで 実習に使用したプログラムを解説していきます。今回はその 1 回目で、ALF(Accelerated Library Framework) 軽量タスクサポートを利用したHello Worldプログラムとプログラム作成のために知っておきたいCell/B.E.のアーキテクチャーについて解説します。

日付:  2010年 3月 05日
レベル:  初級
アクティビティー: 5851 ビュー
お気軽にご意見・ご感想をお寄せください: 


はじめに

Cell/B.E.用のソフトウェア開発キット (Software Development Kit, SDK) にはツールチェーン、ライブラリ、サンプルコード、フレームワークや関連資料が含まれています。フレームワークの一つであるAccelerated Library Framework (ALF) の新しいタスクモデルである、軽量タスクサポート (Lightweight task support, LTS) - ALF LTS と略します - は、SDK3.1から加わりました。ALF LTSは、Cell/B.E. のヘテロジニアスマルチコア環境で必要な様々な定型コード(複数のSPEコアの管理に関するコードなど)を書かずにすむ、多数の機能を提供する便利なフレームワークです。今回は、このフレームワークを使った基本的なプログラム作成のステップについて解説します。ではまず おさらいとして、プログラミングの際に意識することが必要なCell/B.E.プロセッサーの構成から見ていきましょう。

Cell/B.E.の概要

Cell/B.E.は2種類の9個のコアからなるヘテロジニアス(異種混合)マルチコアプロセッサーです。プログラミングにおいては、この2種類のコアの特徴やプロセッサー全体のアーキテクチャーを知ったうえで、その長所を発揮できるようなプログラム構成を考える必要があります。コアの種類や特徴について以下の表に示します。


表1. Cell/B.E.を構成する2種類のコア
コア名個数概要特徴
PowerPC Processor Element (PPE) 1PowerPC汎用プロセッサー互換のコアOSを駆動し、SPEの制御を行う。32KBのL1キャッシュと512KBのL2キャッシュを持ち、PPEだけでPowerPC互換のプログラムを実行することが可能。
Synergistic Processor Element (SPE) 8浮動小数点演算に特化したコア演算を担うSynergistic Processor Unit (SPU) と256KBの専用メモリLocal Store (LS) とから構成される。ベクトル型演算器により、高速演算を行う。SPUが使用するプログラムやデータはDirect Memory Access (DMA) を用いてメインメモリからLSに明示的にロードする必要がある。また、処理結果のデータもDMAを用いてLSからメインメモリに明示的に転送する必要がある。

また、Cell/B.E.の構成を以下の図に示します。


図1. Cell/B.E.の構成

コア以外の説明は以下のようになります。 図1に示すように、各々非常に高速なバンド幅を提供します。

  • EIB (Element Interconnect Bus) : 9個のコアや下記コントローラーを接続するリング状内部バス。
  • MIC (Memory Interface Controller : デュアルチャネルに対応するメモリーコントローラー。
  • BIC (Bus Interface Controller : 周辺デバイスと接続するためのバスコントローラー。

プログラムの概要

このようにCell/B.E.は2種類のコアから構成されており、この構成に対応したプログラム作成が必要です。さらに、最大のパフォーマンスを引き出すためには、コアの特性を意識し、最適化したプログラム作成が必要となります。今回は前者の"コアの構成に対応したプログラム作成"について解説し、次回以降で後者の"コアの特性を意識し、最適化したプログラム作成"について解説します。
では、"コアの構成に対応したプログラム作成"について解説していきましょう。Cell/B.E.内でプログラムが動くイメージを図2に示します。


図2. Cell/B.E.のプログラム動作のイメージ

Cell/B.E.では8個のSPU上で個々にプログラムを実行させます。(SPUは高速な浮動小数点演算処理が得意なため、そのような演算処理をSPUで主に実行させるようにプログラムしますが、これについても次回以降で解説します。) SPUのプログラムを起動するのはPPUで、スレッドとして個々に起動します。SPUは1つのCell/B.E.プロセッサーの中に8個ありますので、SPU側では8個のスレッドが同時に動作可能ということになりますね。
一方、PPUはSPUの制御を行うという使命がありますが、それだけではありません。PowerPC互換のプログラムを実行したり、SPUの苦手な処理を担当したり、並列演算処理を実行することもできます。PPUは1つのCell/B.E.プロセッサーの中に1個だけですが、1つで2個のスレッドが動作します。したがって、トータルとして、1つのCell/B.E.プロセッサーで同時に10個のスレッドを起動することができます。

通常、コアごと(PPU用、SPU用)にプログラムを作成し、PPUから複数のSPUへのプログラムのロードや、スレッドを起動・管理するコードなど、多数の処理コードを作りこむ必要がありますが、この作業を簡潔にする方法が以下のように大きく分けて2種類あります。

  • シングルソースコンパイラを使って1つのプログラムで構成する方法 -- XLC SSC(Single Source Compiler)、CellSs(Cell Superscalar)などを利用
  • フレームワークを利用してプログラミングを簡易化する方法 -- ALF、ALF LTS、OpenCL などを利用

ここでは後者の方法のうち ALF LTS を利用したプログラミングについて解説します。

※ XLC SSCの詳細についてはXLC で行こう!: 第 1 回 Cell/B.E.用 XLC は2種類あるよをご覧ください。

※ CellSsの詳細についてはCell Superscalar はどうだい?: 第 1 回 まずは使ってみようをご覧ください。


ALF LTSの概要

ALF LTSは SDK3.1以降に含まれるフレームワークで、以下のような機能が含まれます。この機能を利用することによって、プログラムを簡潔に作成することができます。たとえば30行ほどの定型コードだけでPPUプログラムを簡潔に作成することができます。

ALF LTSの機能:

  • 複数SPUの管理
  • SPUプログラムの実行時読み込み
  • SPUプログラムの切り替え
  • タスク依存関係の設定

※ SDK3.1の詳細についてはSDK 解説: SDK バージョン 3.1 の紹介をご覧ください。

※ ALF LTSの詳細についてはLet's LTS: 第 1 回 ALF 軽量タスクサポートの概要をご覧ください。


サンプルプログラムの説明

Hello World - ALF LTS版 サンプルコードをダウンロードしてプログラムをご覧ください。この中で4種類の"Hello World"プログラムを紹介しています。プログラムの構成は図1のようになり、(1)から(4)で示すディレクトリーごとに異なる4種類の"Hello World"プログラムを含んでいます。


図3. 4種類のHello World プログラムの構成

(1)から(4)の4種類の"Hello World"プログラムの内容は以下のとおりです。

(1) STEP0_hello_ppu :  PPUだけを使用して"Hello World"を表示する、PowerPC互換のプログラムです。

(2) STEP1_hello_spu :  SPU 1個を使用して"Hello World"を表示するプログラムです。SPUを使用する場合は、通常PPUとSPU両方のプログラミングが必要ですが、ここではSPUだけのプログラムで実行を可能としています。SPUletというプログラミングモデルです。(PPUのプログラムはありませんが、実行時は、通常のプログラムと同様に、SPUの管理はPPUが行っています。)

(3) STEP2_hello_ppu+spu :  SPU 1個を使用して"Hello World"を表示するプログラムです。PPUとSPUの両方のプログラミングを必要とするモデルです。PPUのプログラムは"STEP2_hello_ppu+spu"ディレクトリーの直下に、SPUのプログラムは"spu"ディレクトリーの中に含まれます。

(4) STEP3_hello_ppu+8spu :  SPU 8個それぞれが"Hello World"を表示するプログラムです。(3)との違いは使用するSPUの個数です。SPUのプログラムは(3)のSPUプログラムを使用しています。((3)の"spu"ディレクトリー以下をSPUプログラムとして使用するよう、(4)のMakefileに記述しています。)使用するSPUの個数はPPUプログラムの中で定義しています。

※ 実際のプログラムの開発ステップは (1)→(3)→(4)のように進めることが多いと考えてよいでしょう。(2)のプログラミングモデルは簡単にSPU単体の動作確認を行いたい場合に便利な手法です。

では、(1)から(4)のコードの内容について以下で詳細に説明します。


(1) ステップ 0: PPU

以下に(1)のコードを示します。


リスト1.  main.c


001: #include <stdio.h>  // for printf()
002:
003: int main(int argc, char *argv)
004: {
005:     printf("Hello PPU !!\n");
006: 
007:     return 0;
008: }

PPUを使って"Hello PPU!!"と画面に表示するプログラムです。ここではSPUは使いません。


リスト2.  Makefile


001: PROGRAM_ppu = hello_ppu
002:
003: include $(CELL_TOP)/buildutils/make.footer


Makefileの001行目でプログラムの実行ファイル名を指定しています。003行目では、make.footer という擬似ビルド環境を有効にする定義ファイルを読み込んでいます。ここで CELL_TOPは SDKのあるディレクトリ /opt/cell/sdk/ を示します。環境変数として以下を一旦実行して指定しておけば、003行目のように記述することができます。

    export CELL_TOP=/opt/cell/sdk/

※ 擬似ビルド環境 および make.footerファイルについての詳細はクローズアップ SDK 3.1: 第 2 回 make.footer を使おうをご覧ください。


(2) ステップ 1: SPU

次に(2)のコードを示します。


リスト3.  main_spu.c


001: #include <stdio.h>  // for printf()
002: 
003: int main(unsigned long long speid __attribute__((unused)), 
004:                         unsigned long long parm __attribute__((unused)))
005: {
006:     printf("Hello SPU !!\n");
007:
008:    return 0;
009: }


SPUを使って"Hello SPU!!"と画面に表示するプログラムです。コマンドプロンプトから直接SPU実行ファイル名を入力してプログラムを実行することができます。このプログラムモデルでは、PPUのプログラムを準備する必要はありませんが、ランタイム環境により、SPUへのプログラムのロードやPPUからのSPU制御が行われます。このプログラミングモデルをSPUletと呼んでいます。簡単にSPU単体の動作確認を行いたい場合に便利な手法です。


リスト4.  Makefile


001: PROGRAM_spu = hello_spu
002: LDFLAGS_gcc = -mstdmain
003: include $(CELL_TOP)/buildutils/make.footer


002行目はコンパイルオプションで、スタートアップコードをリンクします。このMakefileを使ってビルドすると、SPU実行ファイル"hello_spu"を作成し、これを直接コマンドプロンプトに入力してSPUのプログラムを起動することができます。


(3) ステップ 2: PPU+1xSPU

次にALF LTSを利用したプログラムをご紹介します。1個のSPUを使って"Hello World!!"を画面に表示します。PPU側のコードを以下に示します。


リスト5.  main.c


001: #include <stdio.h>  // for NULL
002: #include <alf.h>    // for alf_xxxx()
003:
004: int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused)))
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);         //  ALFの初期化 (ALFハンドルの作成)
011:     alf_num_instances_set(handle, 1);  //  ALFの設定:ALFハンドルと使用するSPUの個数(ここでは"1")の設定
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_spu.so"); //  SPUプログラムが格納されている共有ライブラリ名を指定
020:     alf_task_desc_set_int64(task_desc_handle,
021:            ALF_TASK_DESC_ACCEL_IMAGE_REF_L,
022:            (unsigned long long) "hello_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, 1, 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);   //  ALFの終了 (リソースを開放)
033: 
034:     return 0;
035: }


プログラムの流れは、以下のようになります。ALFの初期化と終了の間にタスクに関する一連の処理がはいります。ここでタスクとはSPUで実行する処理のことをいいます。


図4. プログラムの流れ
Program3 Result

コード中のコメントにある説明も合わせてご確認ください。

SPU側で実行するタスクのコードは以下のようになります。


リスト6.  spu/main_spu.c


001: #include <stdio.h>
002: #include <alf_accel.h>
003: 
004: int task_main(
005:         void* p_task_ctx __attribute__((unused)), // タスクコンテキスト -- ホストからの初期データの受け渡し
006:         int instance_id,                           // インスタンス ID -- プログラムが実行されるSPUの番号
007:         int number_of_instance)                    // インスタンス総数 -- 同時に実行しているSPUの数
008: {
009:     printf("[%u/%u] Hello World !!\n",
010:             instance_id,
011:             number_of_instance);
0012:     return 0;
013: }
014:
015: ALF_ACCEL_EXPORT_API_LIST_BEGIN;  // 以下3行でタスクメイン関数の名前をホストから参照するためにエクスポートの設定を行う
016: ALF_ACCEL_EXPORT_API("", task_main);
017: ALF_ACCEL_EXPORT_API_LIST_END;


この(3)のプログラムでは、使用するSPUの数を1個に設定していますので、このプログラムを実行すると以下のように表示されます。"0/1"の 0はSPUのID番号、1は同時に起動しているSPUの個数です。


図5. プログラムの実行結果
Program3 Result

PPU、SPUのプログラムをビルドするための Makefile をそれぞれ以下に示します。


リスト7.  Makefile -PPU用


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


001行目では、SPUのプログラムが存在するディレクトリ名を、002行目では実行ファイル名を指定します。
003行目でALF のライブラリをリンクします。


リスト8.  spu/Makefile -SPU用


001: PROGRAM_spu = hello_spu
002: SHARED_LIBRARY_embed = libhello_spu.so
003:
004: IMPORTS = -lalflts
005:
006: INSTALL_DIR = ..
007: INSTALL_FILES = $(SHARED_LIBRARY_embed)
008:
009: include $(CELL_TOP)/buildutils/make.footer


001行目ではSPUプログラムをコンパイルしたときに生成されるバイナリファイル名を指定しています。
002行目ではSPUプログラムを共有ライブラリに含めるためSHARED_LIBRARY_embed でライブラリ名を指定しています。この002行目で指定するライブラリ名とリスト5のPPU側のコードの019行目で指定するライブラリ名とが一致する必要があります。
004行目でALF のライブラリをリンクします。
006,007行ではこのディレクトリ(/spu)で生成された共有ライブラリをPPU側のディレクトリにコピーしています。


(4) ステップ 3: PPU+8xSPU

(4)は SPUを8個使って動かすプログラムです。(3)とは使用するSPUの数が1個から8個に変わるだけです。
(3)の main.c の 011行でSPUの数を変えてみましょう。
このときのプログラムの説明や実行結果はLet's LTS: 第 1 回 ALF 軽量タスクサポートの概要をご覧ください。



ダウンロード

内容ファイル名サイズダウンロード形式
サンプルプログラムご使用条件 (必ずお読みください)readme.pdf105KBHTTP
Hello World - ALF LTS版 サンプルコードHello_World_AlfLts.zip107KBHTTP

ダウンロード形式について


参考文献

学ぶために

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

議論するために

著者について

森 由美の肖像写真

著者は日本アイ・ビー・エムで数年にわたって画像処理検査装置などのソリューション開発を行ってきました。本記事をとおして少しでもみなさまのお役に立てればと思います。最近は国際宇宙ステーションが見える日をチェックしては朝焼け前の星空を眺めて宇宙のロマンにひたっています。(森由美 日本アイ・ビー・エム(株)ハイブリッドシステム開発に所属、工学博士)

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Multicore acceleration, Sample IT projects
ArticleID=469718
ArticleTitle=Cell プログラミングおさらい: Hello World again
publish-date=03052010
author1-email=morip@jp.ibm.com
author1-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。