本サイトは、マルチコア トータルソリューションカンパニー -フィックスターズの技術者有志が運営するサイトです。

3.2 簡単なSPEプログラム

出典: PS3 Linux Information Site / Cell/B.E.のパワーを体験しよう

 ここでは、libspe2を利用した基本的なプログラミング方法について解説します。SPEプログラミングの手始めとして、1基のSPEを利用した簡単なプログラムを例にSPEプログラムの実行の流れについて見ていきます。

3.2.1 SPEプログラムの実行の流れ

 libspe2では、以下の手順に従いPPEプログラムからSPEプログラムを実行します。

 PPEセントリック・モデルにおける典型的なSPEプログラムの実行の流れを図 3.1に示します。

(1) SPEプログラム・イメージのオープン
(2) SPEコンテキストの生成
(3) SPEプログラムのLSへのロード
(4) SPEプログラムの実行
(5) SPEコンテキストの破棄
(6) SPEプログラム・イメージのクローズ

 手順 (1) ~ (6) を図に示すと、図 3.3のようになります。

画像:FIGURE-03-03.png

図 3.3 SPEプログラム実行手順


 以降では、具体的なプログラムを用いて、それぞれの手順について説明します。


3.2.2 Hello Worldプログラム

 リスト (3-1) は、「Hello world!」を表示するSPEプログラムです。このプログラムを例にPPEプログラムからSPEプログラムを実行する基本的なプログラミング方法について解説します。

リスト (3-1) Hello Worldプログラム (SPE用プログラム)

1 #include <stdio.h>
2 
3 int main(unsigned long long spe, unsigned long long argp, unsigned long long envp)
4 {
5     printf("Hello world!\n");
6 
7     return 0;
8 }


(1) SPEプログラム・イメージのオープン

 まず、spe_image_open()関数を用いて、ELF実行ファイルに格納されたSPEプログラム・イメージをオープンします。


API定義 (3-1) spe_image_open()関数のプロトタイプ宣言

spe_program_handle_t * spe_image_open(const char *filename);
第1引数 filename SPEプログラムのELF実行ファイルのパス (絶対パスもしくは相対パス) を指定します。
返値 成功時には、オープンされたSPEプログラム・イメージのハンドルへのポインタを返します。失敗時には、NULLを返しerrnoにエラーコードを設定します。


 用例 (3-1) にspe_image_open()関数の使用例を示します。


用例 (3-1) SPEプログラム・イメージをオープンする

prog = spe_image_open("./spe_hello.elf");


(2) SPEコンテキストの生成

 続いて、spe_context_create()関数を用いて、SPEコンテキストを生成します。


API定義 (3-2) spe_context_create()関数のプロトタイプ宣言

spe_context_ptr_t spe_context_create(unsigned int flags,
                                     spe_gang_context_ptr_t gang);
第1引数 flags SPEコンテキストの動作を設定するフラグを指定します。本チュートリアルでは、このフラグは利用しないため、デフォルト値0を設定します。
第2引数 gang SPE ギャングコンテキストを指定します。SPEギャングコンテキストは、本チュートリアルでは利用しないため、NULLを指定します。SPEギャングコンテキストの詳細についてはリファレンス「SPE Runtime Management Library version 2.0」の用語定義 (Terminology) を参照してください。
返値 成功時には、SPEコンテキストへのポインタを返します。失敗時には、NULLを返し、errnoにエラーコードを設定します。


 なお、生成されたSPEコンテキストは、アプリケーション側で不要になり次第、後述するspe_context_destroy()関数で破棄する必要があります。用例 (3-2) にspe_context_create()関数の使用例を示します。


用例 (3-2) SPEコンテキストを生成する

spe = spe_context_create(0, NULL);


(3) SPEプログラムのLSへのロード

 SPEコンテキストの準備ができたら、spe_program_load()関数を用いて、(1)でオープンされたSPEプログラムをLSへロードします。


API定義 (3-3) spe_program_load()関数のプロトタイプ宣言

int spe_program_load(spe_context_ptr_t spe,
                     spe_program_handle_t *program);
第1引数 spe SPEコンテキストへのポインタを指定します。
第2引数 program LSへロードするSPEプログラム・イメージのハンドルへのポインタを指定します。
返値 成功時には、0を返します。失敗時には、-1を返し、errnoにエラーコードを設定します。


 用例 (3-3) にspe_program_load()関数の使用例を示します。


用例 (3-3) SPEプログラムをLSへロードする

ret = spe_program_load(spe, prog);


(4) SPEプログラムの実行

 SPEコンテキストにロードされたプログラムは、spe_context_run()関数により実行されます。


API定義 (3-4) spe_context_run()関数のプロトタイプ宣言

int spe_context_run(spe_context_ptr_t spe,
                    unsigned int *entry,
                    unsigned int runflags,
                    void *argp,
                    void *envp,
                    spe_stop_info_t *stopinfo);
第1引数 spe 実行させるSPEコンテキストへのポインタを指定します。
第2引数 entry 実行開始アドレスを格納した変数へのポインタを指定します。通常は、実行開始アドレスとしてSPE_DEFAULT_ENTRYを使用します。
第3引数 runflags 特別な振る舞いをさせるためのフラグを指定します。通常は、0を指定します。
第4引数 argp SPEプログラムのmain()関数の第2引数に渡す値を指定します。
第5引数 envp SPEプログラムのmain()関数の第3引数に渡す値を指定します。
第6引数 stopinfo SPEプログラムが停止した時の詳細情報を格納する変数へのポインタを指定します。
返値 成功時には、0以上の値を返します。失敗時には、-1を返し、errnoにエラーコードを設定します。


 引数の詳細な仕様についてはリファレンス「SPE Runtime Management Library Version 2.0」を参照して下さい。

(http://67.117.136.164/pub/cell/linux-20061110-docs/libspe-v2.0.pdf)

 spe_context_run()関数が呼ばれると、SPEプログラムへ処理が移ります。SPEプログラムが終了した後、呼び出し元のPPEプログラムへと処理が戻ります。SPEプログラムのmain()関数から戻ってくる、もしくはSPEプログラムがexit()関数を呼んだ場合、返値として0が返されます。それ以外の場合、0以外の値が返されます。SPEプログラムの停止に関する詳しい情報がある場合には、第6引数stopinfoに指定した領域に格納されます。用例 (3-4) にspe_context_run()関数の使用例を示します。


用例 (3-4) SPEプログラムを実行する

ret = spe_context_run(spe, &entry, 0, NULL, NULL, &stop_info);


(5) SPEコンテキストの破棄

 SPEプログラムの実行を終え、アプリケーションにとって不要になったSPEコンテキストは、spe_context_destroy()関数により破棄します。


API定義 (3-5) spe_context_destroy()関数のプロトタイプ宣言

int spe_context_destroy(spe_context_ptr_t spe);
第1引数 spe 破棄したいSPEコンテキストへのポインタを指定します。
返値 成功時には、0を返します。失敗時には、-1を返し、errnoにエラーコードを設定します。


 用例 (3-5) にspe_context_destroy()関数の使用例を示します。


用例 (3-5) SPEコンテキストを破棄する

ret = spe_context_destroy(spe);


(6) SPEプログラム・イメージのクローズ

 最後に、spe_image_close()関数を用いて、(1)でオープンされたSPEプログラム・イメージをクローズします。


API定義 (3-6) spe_image_close()関数のプロトタイプ宣言

int spe_image_close(spe_program_handle_t *program);
第1引数 program クローズしたいSPEプログラム・イメージのハンドルへのポインタを指定します。
返値 成功時には、0を返します。失敗時には、-1を返し、errnoにエラーコードを設定します。


 用例 (3-6) にspe_image_close()関数の使用例を示します。


用例 (3-6) SPEプログラム・イメージをクローズする

ret = spe_image_close(prog);

 ここまでが、libspe2を用いてPPEプログラムからSPEプログラムを実行する基本的なプログラミング方法となります。

3.2.3 例題プログラムの解説

 それでは、例題プログラムのソースコード全体について解説します。


例題プログラム (3-1) Hello Worldプログラム (PPE用プログラム)

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <libspe2.h>
 4
 5 int main(int argc, char **argv)
 6 {
 7     int ret;
 8
 9     spe_context_ptr_t spe;
10     spe_program_handle_t *prog;
11     unsigned int entry;
12     spe_stop_info_t stop_info;
13
14     prog = spe_image_open("hello_spe.elf");
15     if (!prog) {
16         perror("spe_image_open");
17         exit(1);
18     }
19
20     spe = spe_context_create(0, NULL);
21     if (!spe) {
22         perror("spe_context_create");
23         exit(1);
24     }
25
26     ret = spe_program_load(spe, prog);
27     if (ret) {
28         perror("spe_program_load");
29         exit(1);
30     }
31
32     entry = SPE_DEFAULT_ENTRY;
33     ret = spe_context_run(spe, &entry, 0, NULL, NULL, &stop_info);
34     if (ret < 0) {
35         perror("spe_context_run");
36         exit(1);
37     }
38
39     ret = spe_context_destroy(spe);
40     if (ret) {
41         perror("spe_context_destroy");
42         exit(1);
43     }
44
45     ret = spe_image_close(prog);
46     if (ret) {
47         perror("spe_image_close");
48         exit(1);
49     }
50
51     return 0;
52 }
3行目 SPEを制御する時に必要なヘッダファイル“libspe2.h”をインクルードします。
9行目~12行目 SPEプログラムおよびSPEコンテキストを扱うための変数を宣言します。
14行目 spe_image_open()関数を用いて、実行したいSPEプログラム・イメージをオープンします。
20行目 spe_context_create()関数を用いて、SPEコンテキストを生成します。
26行目 spe_program_load()関数を用いて、SPEプログラムをLSにロードします。
33行目 spe_context_run()関数により、SPEプログラムを実行します。
39行目 spe_context_destroy()関数を用いて、実行処理の終わったSPEコンテキストを破棄します。
45行目 spe_image_close()関数を用いて、SPEプログラム・イメージをクローズします。


例題プログラム (3-2) Hello Worldプログラム (SPE用プログラム)

1 #include <stdio.h>
2 
3 int main(unsigned long long spe, unsigned long long argp, unsigned long long envp)
4 {
5     printf("Hello world!\n");
6 
7     return 0;
8 }
3行目 main()関数の第1引数speにはSPEコンテキストの実効アドレスが渡されます。また、第2引数argp、第3引数evnpには、PPE側で呼び出されたspe_context_run()関数の第4引数argp、第5引数envpがそれぞれ渡されます。
5行目 文字列“Hello world!”を標準出力に出力します。


 Hello Worldプログラムのソースコードは以下のリンクからダウンロードできます。

ファイルダウンロード:hello.tar.gz

3.2.4 プログラムのコンパイルと実行

 ここでは、プログラムのコンパイル方法と実行方法について解説しますが、あらかじめ第1.4節の手順に従って開発環境を構築してください。SPEを利用したアプリケーションは、PPEプログラムとSPEプログラムから構成されていますので、それぞれのソースコードをコンパイルし、双方のELF実行ファイルを作成する必要があります。

 PPEプログラムのコンパイルには、gccコマンドを利用します。libspe2を利用するため、gccのリンカオプションとして-lspe2オプションを指定し、libspe2.soをリンクします。また、SPEプログラムのコンパイルには、spu-gccコマンドを利用します。用例 (3-7) にHello Worldプログラムの場合のコンパイル方法を示します。


用例 (3-7) プログラムのコンパイル

$ gcc -lspe2 hello_ppe.c -o hello_ppe.elf
$ spu-gcc hello_spe.c -o hello_spe.elf


 アプリケーションを実行するには、2つのプログラムのうちPPEプログラムのほうをシェルプロンプト上で起動してください。用例 (3-8) にHello Worldプログラムの場合の実行方法を示します。


用例 (3-8) プログラムの実行

$ ./hello_ppe.elf
Hello world!
$ 

第3.1節」へ戻る 第3章目次 第3.3節」へ進む
チュートリアル目次
表示
個人用ツール
オープンソースプロジェクト
ツールボックス