l'essentiel est invisible pour les yeux

Sunday, December 03, 2006

[Cell] PPUプログラムにSPUプログラムを組み込む

SPUプログラムは静的ライブラリとしてPPUプログラムに組み込んでコンパイルすることができる。組み込みでコンパイルした際は、PPUプログラムからextern属性をつけて実行プログラム名でspe_program_handle_t型の変数として参照することが出来る。

組み込みSPEを作るには、オブジェクトファイルを作成してからppu-embedspuコマンドで組み込み用のオブジェクトファイルを作成し、ppu-arコマンドで静的ライブラリを作成する。次の例は、hello_spuというSPUプログラムから組み込み用の静的ライブラリを作成する。


% spu-gcc -o hello_spu hello_spu.o -Wl,-N /opt/IBM/cell-sdk-1.1/sysroot/usr/spu/lib/libc.a
% ppu-embedspu -m64 hello_spu hello_spu hello_spu-embed64.o
% ppu-ar -qcs hello_spu.a hello_spu-embed64.o


ppu-gccでリンクする際に作成した静的ライブラリも合わせてリンクするとPPUプログラム内で次のようにして実行イメージを参照可能になる。


extern spe_program_handle_t spe_program;


組み込みSPUを使用した、簡単なプログラムを作成した。
ファイル&ディレクトリの構成は次の通り。

% ls -R
.:
Makefile ppu/ ppu_time.h spu/

./ppu:
Makefile spu_program_embed.c

./spu:
Makefile hello_spu.c
%


ppu/spu_program_embed.c

#include <stdio.h>
#include <libspe.h>
#include <errno.h>
#include <sched.h>
#include <stdint.h>
#include "../ppu_time.h"

extern spe_program_handle_t hello_spu;

int main () {
int status;
spe_gid_t gid;
speid_t spe_id;
uint32_t ts, te;

StartTimer(ts);
puts("Starting PPE program.");
gid = spe_create_group(SCHED_OTHER, 0, 1);
if(gid == 0) {
fprintf(stderr, "Failed spe_create_group(errno=%d)\n", errno);
return 1;
}
if(spe_group_max(gid) < 1) {
fprintf(stderr, "System doesn't have a working SPE.\n");
return 1;
}

spe_id = spe_create_thread(gid, &hello_spu, NULL, NULL, -1, 0);
if(spe_id == 0) {
fprintf(stderr, "Failed spe_create_thread(errno=%d)\n", errno);
return 1;
}
printf("Waiting SPE thread...\n");
spe_wait(spe_id, &status, 0);
printf("done.\n");
StopTimer(te, ts);

PrintTimer(te);

return 0;
}


spu/hello_spu.c

#include <stdio.h>

int main(unsigned long long speid, unsigned long long argp) {
puts("SPE: Hello, world!");
return 0;
}


コンパイルはCell SDKで提供されているMakefile(make.footer)を使用すると簡単である。
./Makefile

DIRS = spu ppu
include /opt/IBM/cell-sdk-1.1/make.footer


ppu/Makefile
IMPORTSを設定して、静的ライブラリをリンク時に含めるようにする。

PROGRAM_ppu64 = ./spu_program_embed
IMPORTS = ../spu/hello_spu.a -lspe
CC_OPT_LEVEL = -O0
include /opt/IBM/cell-sdk-1.1/make.footer


spu/Makefile
LIBRARY_embed64に静的ライブラリ名を設定すると、自動的に作成してくれる。

PROGRAMS_spu := hello_spu
LIBRARY_embed64 := hello_spu.a
IMPORTS = $(SDKLIB_spu)/libc.a
include /opt/IBM/cell-sdk-1.1/make.footer


実行結果

% ./spu_program_embed
Starting PPE program.
Waiting SPE thread...
SPE: Hello, world!
done.
time: 0.83680(msec)
%

spe_open_imageでSPE実行プログラムを読み込む方法と組み込み方法の実行時間を比較してみた。





















回数組み込みspe_open_image
1回目0.881480(msec)0.840640(msec)
2回目0.835840(msec)0.838560(msec)
3回目0.833240(msec)0.838640(msec)

実行速度はほぼ同じだった。(シュミレータ上で実行した事が原因?)