Cellプログラミングにはいくつかのプログラミングモデルが存在する。
Cell上でのプログラミングモデルを順を追って紹介してみる。
第一回は、PPEとSPEの間でRemote Procedure Callを行うFunction-Offloadモデルと呼ばれるプログラミングモデルで一番単純なHello worldを書いてみた。このプログラミングモデルは、PPEからSPE上のプロシージャをPPE上で定義されたプロシージャのように呼び出すことが出来るRPCを実現する。
前回の記事、SPE上で実行時間を計測するでは、SPEの実行プログラムをオープンしSPEスレッドを作成して処理を実行し、そして処理が終了するのを待ってから、SPEプログラムハンドラを閉じて終了した。
spe_open_image();
spe_create_thread();
spe_wait();
spe_close_image();
Function-Offloadモデルでは、プログラム単位でSPEに処理をさせるのではなく、プロシージャ単位でSPUを使用して処理を並列化することを可能にする。Cell上ではスタブを利用することでMDAやMFCといった低レベルの詳細を知ることなく、PPE上からSPE上のプロシージャを実行することが可能になる。スタブがプロキシの役割を果たしPPEとSPEの通信の詳細であるDMA転送やMFCといった細かくて面倒な処理をラップしてくれる。
IDLのパラメータ定義やPPEからSPE上のプロシージャを呼び出すRPCの仕組みの詳細についてはとりあえず保留。
始めにプロシージャのインタフェースをIDLファイルで定義する。そのファイルをCBE SDKが提供するIDLコンパイラでコンパイルすることで、スタブクラスのソースコード(C言語)を作成してくれる。
初めに、IDLコンパイラの実行ファイルが存在しなかったのでビルドする。
% sudo yum install byacc flex
% cd /opt/IBM/cell-sdk-1.1/src/tools/idl
% make
% ls /opt/IBM/cell-sdk-1.1/host/bin/idl
/opt/IBM/cell-sdk-1.1/host/bin/idlという実行バイナリができあがる。
では、Function-Offload モデルを利用して"Hello World!"を書いていく。
始めに次のように作業用ディレクトリを作成する。ファイルについては順に作っていく。
% ls -FR
.:
Makefile hello.idl ppu/ spu/
./ppu:
Makefile hello.c
./spu:
Makefile hello.c
%
Function Offloadモデルでプログラミングを行うには、3つのソースファイルを作成する必要がある。
- PPE上で実行するメインファイル
- SPE上で実行するプロシージャ
- プロシージャのインタフェースを定義したIDLファイルである。
stub.hはIDLコンパイラにより自動生成される。
IDLファイルでhelloという名前のプロシージャーを定義する。[in]と指定されているのは関数への入力のための引数で、[out]と指定される場合は出力のための引数。返り値はつねにidl_id_t型で無ければならない。(その他については別途説明)
helloは、第一引数に文字列のサイズ、第二引数に文字列へのポインタを引数として受け取る。
interface greeting
{
import "../stub.h";
[sync] idl_id_t hello ([in] int nbytes, [in, size_is(nbytes)] char message[]);
}
このIDLファイルからスタブクラスを作成するためのMakeファイルを定義する。
########################################################################
# Subdirectories
########################################################################
DIRS := ppu spu
########################################################################
# Local Defines
########################################################################
IDL_SRC := hello.idl
IDL_FLAGS := -i -p ppu/stub_hello.c -s spu/stub_hello.c -n 4 -b spu_hello
INCLUDE = -I $(SDKINC) -I spu
include /opt/IBM/cell-sdk-1.1/make.footer
-b引数はスタブをプロキシとして実行されるSPUプログラム名、-n引数は割り当てるSPUの最大数を設定する。
makeを実行すると、ppu/stub_hello.cとspu/stub_hello.cというスタブが作成される。合わせてstub.hというヘッダが作成されるのでPPEとSPEプログラム上からこのヘッダを読み込むことでプロシージャを利用することが出来る。
次にPPU上で実行するプログラムppu/hello.cを書く。
#include <stdio.h>
#include <string.h>
#include <libidl.h> // stub.hの前に読み込む
#include "../stub.h"
int main() {
char *str = "Hello, World!";
hello(strlen(str), str);
return 0;
}
SPEプログラムにhelloプロシージャーの実装の詳細を定義する。
返り値はidl_id_tで固定。引数はIDLファイルで定義したものと合わせる。
PPE/SPEプログラムをコンパイルするためのMakefileを次のように書く。
#include <stdio.h>
#include <stdlib.h>
#include <idl_util.h>
#include "../stub.h"
idl_id_t hello(int nbytes, char msg[]) {
printf("SPE: %s\n", msg);
return 0;
}
ppu/Makefile
########################################################################
# Target
########################################################################
PROGRAM_ppu = ppu_hello
########################################################################
# Objects
########################################################################
IMPORTS = $(SDKLIB)/libidl.a $(SDKLIB)/libmisc.a -lspe
########################################################################
# make.footer
########################################################################
include /opt/IBM/cell-sdk-1.1/make.footer
spu/Makefile
########################################################################
# Target
########################################################################
PROGRAM_spu = ./spu_hello
########################################################################
# make.footer
########################################################################
include /opt/IBM/cell-sdk-1.1/make.footer
作業ディレクトリのトップディレクトリでmakeしシミュレータ上に転送する。
% make
% cp ppu/ppu_hello spu/ppu_hello /tmp/
シミュレータ上でゲストOSから/tmp/ppu_helloと/tmp/spu_outを転送する。
# callthru source /tmp/ppu_hello > ppu_hello
# callthru source /tmp/spu_hello > spu_hello
# chmod +x ppu_hello spu_hello
# ./ppu_out
SPE: Hello, World!
#
見事にHello, WorldをFunction-Offloadモデルを使用し、SPE上で実行させることが出来た。