Cerium Task Manager
Blender / SceneGraph
結局、Video Chip に触れない
SPUでレンダリング
ソフトレンダリングにしては速いが...
新型PS3では、Linux は使えない
とかいろいろだめ
Linux 側から使える SPE は 6 個
SPE は 256KB の Local Store (LS)
SPE からメインメモリへ直接アクセスできない (DMAを使う)
SPE は 128 ビットレジスタを 128 個持っている
Single Thread でもPPE がクソ遅いので、SPEで実行するべき
例えば、
Word Count
Task には依存関係がある
Open/CL , Spurs Engine
結局、これしかないらしい。
Row Level での並列性
Vector/Streaming
結局、データ並列とパイプライン
SPE Level での
データ読み込み、 実行、データ書込
のパイプライン並列
High Level での並列性
Rendering
Scene Graph
パイプラインバッファはいくつ?
処理中に必要なデータがメインメモリ上にあるメインメモリ(256MB、広くはないが十分)から、256Kに必要なだけキャッシュする
でも、SPE には、256k しかメモリがない
ハードウェアでやれよ!なので、自分でキャッシュする必要がある
普通の並列ハードウェアはキャッシュになっている
IBMはそう提案したらしいが、SCEの人が拒否したらしい
Open/GL Mesa に Cell driver を書いたが、そんな経緯で作成することに...
メインメモリに依存しすぎ
Task base で書く必要がある
Redering Engine も自前で一つ持っていて良い
SPEは256Kなのでコード管理も必要
SPURSは公開されないらしい
PPU/SPUで、Task の互換性がある
SPU上の最適化は当面禁止
OS X 上でも動く
コードのデバッグはOS X 上でやる
並列化とチューニングだけPS3上で行なう
SPU上のメモリをCode と Data を Hash とメモリリストで管理する
SPUに入り切らない巨大なTaskでも実行できる
Blender で、3Dモデリング
階層化、グルーピング
これを、Blender の Python plugin で XMLに変換
画像/Texture もXMLに埋め込まれる
XMLを読み込み SceneGraph を作る
以下にexport_xml.py をコピー
ゲームの初期化部分でcrateFromXMLfileを呼ぶ
void
game_init(TaskManager *manager, int bg)
{
sgroot->createFromXMLfile(manager, "xml_file/SG.xml");
...
階層化された3DオブジェクトSceneGraph のノードには、
子供の向きを決定する変換行列
Camera
背景
入力デバイス
MoveTask
Collision Task
がある
SceneGraph をこれで、すべて書ける。
MoveTask
CollsionTask
で書き換えていく
MoveTask, CollsionTask は、ステートパターンで
入れ換えられる
SceneGraph の構築だけを書けば、あとは、Cell が自動的に並列に実行してくれる
MoveTask
CollsionTask
class SpeTask : public SchedTask {
SchedConstructor( SpeTask );};
int run(TaskManager *manager, void *rbuf, void *wbuf);
run 関数は Task における main 関数のようなもの
SchedConstructor() で class 名を登録する
(C++のnew を使うとメモリを食われる...)
SchedRegisterTask(TASK_SPE, SpeTask) で SpeTask に TASK_SPE という ID をつけて
登録します
/* 先ほど登録した ID を指定して Task を生成 */
HTaskPtr task = manager->create_task(TASK_SPE);
/* 入出力先の指定 */
task->add_inData(rbuff, rbuff_SIZE);
task->add_outData(wbuff, wbuff_SIZE);
/* CPU の指定 */
task->set_cpu(SPE_ANY);
/* Task の投入 */
task->spawn();
/* taskB は taskA が終わるまで待つ */
taskB->wait_for(taskA);
/* taskC は taskB が終わるまで待つ */
taskC->wait_for(taskB);
既存のプログラミングでは、まったく歯が立たないトリビアルなプログラムでも、並列にする必要がある
Task をグラフ構造的に構築する (SceneGraphのMoveTask)
File を mmap する
mmap した部分をTask に割り当て、word countする
Task の構築
Task の依存関係
char *file_mmap = st_mmap.file_mmap;
int word_flag = 0;1)*division_size-1] != 0x0A));
int i;
for (i = 0; i < task_num; i++) {
t_exec = manager->create_task(TASK_EXEC);
t_exec->add_inData(file_mmap + i*division_size, division_size);
t_exec->add_outData(o_data + i*status_num, division_out_size);
t_exec->add_param(division_size);
t_exec->add_param(word_flag);
t_exec->set_cpu(SPE_ANY);
t_print->wait_for(t_exec);
t_exec->spawn();
word_flag = ((file_mmap[(i+1)*division_size-1] != 0x20) && (file_mmap[(i+
size -= division_size;
}
....
/* taskの数 */
int task_num = size / division_size;
int out_task_num = task_num + (division_size*task_num < size);
t_print = manager->create_task(TASK_PRINT);
t_print->add_inData(o_data, out_size);
t_print->add_param(out_task_num);
t_print->add_param(status_num);
最初に大量のTaskをすべて作る
Task が自分でデータを拾って来る
Task 同士が、同期を行なう
Task 内では同期はしない
Local Storage/専有したメインメモリしか使わない
Task が終了した時に、Single Thread で動いているPPE
がデータの整理/同期を行なう
Task 側では、Task の生成は行なわない
Task の post_func (continuation) で、Taskを生成する
Task 内で生成しても即座には実行されないPPE Task
Task 終了時に、SPEに送る Task List が作られる
Task List のアドレスがSPEにメールされる
SPEがメールを見て、Task List を読み込み実行する
Task List の読み込みとSPEのTaskの実行は並列
Task List がなくなる(なくなりそうになると)と、
PPEにメールで要求する
SPE Task と互換。メインメモリを自由に参照できる
全部、同じCPU上で実行する。
OS X 上で動作する (Linux でも)
デバッグ用
get_segment/put_segment/wait_segement特に、
明示的にキャッシュ制御する必要がある
Dynamic SPE Task
SPE上に常駐しないTask256K (GBAと同じ!?) しかメモリがないので重要
MemList と Hash で管理されている
GCCのOverlayを使う
Overlay では、異なる場所にコードを置けない
部分的にPICではなく、絶対参照に変更する
自分自身へは相対参照。ライブラリへは絶対参照
Perl Script で書き換える
task_list にオブジェクト生成するコードを入れる
オブジェクトが生成されてしまえば、普通に扱える
task 実行中にコードが追い出されることはない
現在実行中のコード
次にロードするコード
の二つは必ずメモリ上にある
SceneGraph -> SceneGraph
SceneGraph -> Polygon
Polygon -> Span Pack
Span Pack を Texture を使って Rendering
これらを大きく並列に実行する
Rendering は細かく並列に実行する
1 dot 1 dot SPUが書いていく
相互制約が非常に大きい物理シミュレーションの例(地味です...)
非ホロノミック系なので、単純な積分では力学を決定できない
SPU上で、すべての要素を同時に計算する必要がある
(あまり並列計算向きではない...ベクトル向き)
SceneGraphを作れば、move/collision を記述するだけで並列に実行される
ソフトウェアレンダリングなんで、なんでも自分で書ける