diff presen/osc2010.ind @ 0:9887d6547572

presen not done.
author tkaito
date Wed, 29 Sep 2010 22:55:09 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/presen/osc2010.ind	Wed Sep 29 22:55:09 2010 +0900
@@ -0,0 +1,398 @@
+-title: 2009-09-26 (土)   Cerium を用いた PS3 でのゲームの作り方
+
+--Linux 上でのゲームフレームワーク
+
+   Cerium Task Manager
+
+   Blender / SceneGraph
+
+--Cell ってどうなの?
+
+   結局、Video Chip に触れない
+   SPUでレンダリング 
+     ソフトレンダリングにしては速いが...
+
+   新型PS3では、Linux は使えない
+   とかいろいろだめ
+
+--Cell Architecture
+
+<img src="photo/Cell-main2.png" alt="pipeline" height="200">
+
+Linux 側から使える SPE は 6 個
+SPE は 256KB の Local Store (LS) 
+SPE からメインメモリへ直接アクセスできない (DMAを使う)
+SPE は 128 ビットレジスタを 128 個持っている
+
+
+--楽するための並列プログラム
+
+トリビアルなプログラムでも並列実行する必要がある
+
+Single Thread でもPPE がクソ遅いので、SPEで実行するべき
+
+例えば、
+
+    Word Count
+
+--プログラムを Task に分割
+
+Task には依存関係がある
+
+Open/CL , Spurs Engine 
+
+--並列性
+
+	データ並列
+	パイプライン
+
+結局、これしかないらしい。
+
+--階層的並列プログラミング
+
+      Row Level での並列性 
+        Vector/Streaming
+        結局、データ並列とパイプライン
+
+      SPE Level での
+        データ読み込み、 実行、データ書込
+        のパイプライン並列
+
+      High Level での並列性
+        Rendering
+        Scene Graph
+
+-- データ読み込み、 実行、データ書込 
+
+<img src="photo/pipeline.jpg" alt="pipeline" height="300">
+
+パイプラインバッファはいくつ?
+
+--Task は良いけど、データはどうするの?
+
+データを右から左に...
+     処理中に必要なデータがメインメモリ上にある
+     でも、SPE には、256k しかメモリがない
+
+メインメモリ(256MB、広くはないが十分)から、256Kに必要なだけキャッシュする
+     ハードウェアでやれよ!
+     普通の並列ハードウェアはキャッシュになっている
+     IBMはそう提案したらしいが、SCEの人が拒否したらしい
+
+なので、自分でキャッシュする必要がある
+
+--Cerium Task Manager
+
+       Open/GL Mesa に Cell driver を書いたが、
+       メインメモリに依存しすぎ
+       Task base で書く必要がある
+       Redering Engine も自前で一つ持っていて良い
+       SPEは256Kなのでコード管理も必要
+       SPURSは公開されないらしい
+
+そんな経緯で作成することに...
+
+--Crium Task Manager の特徴
+
+       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 を作る
+
+<img src="photo/cerium_sg_tree.jpg" alt="sg" >
+
+--Blender から SceneGraph 用の xml 生成
+
+PythonScript の導入
+
+<ol>
+<li> Blender をダウンロードしてインストール</li>
+<li> export_xml.py を用意する</li>
+<li>"/Applications/blender-version/blender.app/Contens/MacOS/.blender/scripts
+"
+           以下にexport_xml.py をコピー</li>
+<li>Blender を起動すると File -> Export に Libps3 (.xml) が追加される</li>
+</ol>
+
+ゲームの初期化部分でcrateFromXMLfileを呼ぶ
+<font size="4"><pre>
+void
+game_init(TaskManager *manager, int bg)
+{
+   sgroot->createFromXMLfile(manager, "xml_file/SG.xml");
+...
+</pre></font>
+
+--SceneGraph
+
+       階層化された3Dオブジェクト
+       子供の向きを決定する変換行列
+       Camera
+       背景
+       入力デバイス
+
+SceneGraph のノードには、
+       MoveTask
+       Collision Task 
+
+       がある
+
+--ゲームとは、
+
+       SceneGraph を
+         MoveTask
+         CollsionTask
+      で書き換えていく
+         MoveTask, CollsionTask は、ステートパターンで
+         入れ換えられる
+
+これで、すべて書ける。
+
+--つまり、
+
+    SceneGraph の構築
+    MoveTask
+    CollsionTask
+だけを書けば、あとは、Cell が自動的に並列に実行してくれる
+
+--Task の作り方
+
+SchedTask を継承した class を作る
+<pre>
+class SpeTask : public SchedTask {
+    SchedConstructor( SpeTask );
+    int run(TaskManager *manager, void *rbuf, void *wbuf);
+};
+</pre>
+
+run 関数は Task における main 関数のようなもの
+SchedConstructor() で class 名を登録する
+(C++のnew を使うとメモリを食われる...)
+
+SchedRegisterTask(TASK_SPE, SpeTask) で SpeTask に TASK_SPE という ID をつけて
+登録します
+
+
+--Task の作り方(Con't)
+<pre>
+/* 先ほど登録した 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();
+</pre>
+
+--Task の作り方(Con't)
+Task は依存関係を記述する事ができる
+<pre>
+/* taskB は taskA が終わるまで待つ */
+taskB->wait_for(taskA);
+
+/* taskC は taskB が終わるまで待つ */
+taskC->wait_for(taskB);
+</pre>
+
+--並列アーキテクチャは並列でないと...
+
+特に、Cell/PS3 は、SPUで実行しないとだめ
+     既存のプログラミングでは、まったく歯が立たない
+
+トリビアルなプログラムでも、並列にする必要がある
+
+--WordCount
+
+      Task をグラフ構造的に構築する (SceneGraphのMoveTask)
+      File を mmap する
+      mmap した部分をTask に割り当て、word countする
+      Task の構築
+      Task の依存関係
+
+    char *file_mmap = st_mmap.file_mmap;
+
+--WordCount
+
+<img src="photo/wc_graf1.jpg" alt="sg" height="300">
+
+--WordCount 
+
+    int word_flag = 0;
+    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+
+1)*division_size-1] != 0x0A)); 
+        size -= division_size;
+    }
+</pre>
+
+--WordCount 各SPEの結果を合計
+<pre>
+       ....
+    /* 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);
+</pre>
+
+
+
+--やってはいけないこと
+
+      最初に大量のTaskをすべて作る
+      Task が自分でデータを拾って来る
+      Task 同士が、同期を行なう
+
+--Cerium Engine での同期
+
+      Task 内では同期はしない
+      Local Storage/専有したメインメモリしか使わない
+
+      Task が終了した時に、Single Thread で動いているPPE
+      がデータの整理/同期を行なう
+
+      Task 側では、Task の生成は行なわない
+      Task の post_func (continuation) で、Taskを生成する
+
+--SPE Task, PPE Task
+      Task 内で生成しても即座には実行されない
+      Task 終了時に、SPEに送る Task List が作られる
+      Task List のアドレスがSPEにメールされる
+      SPEがメールを見て、Task List を読み込み実行する
+      Task List の読み込みとSPEのTaskの実行は並列
+      Task List がなくなる(なくなりそうになると)と、
+           PPEにメールで要求する
+
+PPE Task
+      SPE Task と互換。メインメモリを自由に参照できる
+
+--Fifo TaskManager
+
+全部、同じCPU上で実行する。
+
+OS X 上で動作する (Linux でも)
+
+デバッグ用
+
+--MemList と Hash
+
+      get_segment/put_segment/wait_segement
+      明示的にキャッシュ制御する必要がある
+
+特に、
+
+Dynamic SPE Task
+      SPE上に常駐しないTask
+      MemList と Hash で管理されている
+
+256K (GBAと同じ!?) しかメモリがないので重要
+
+--SPU上でのコード管理
+
+       GCCのOverlayを使う 
+       Overlay では、異なる場所にコードを置けない
+         部分的にPICではなく、絶対参照に変更する
+
+       自分自身へは相対参照。ライブラリへは絶対参照
+       Perl Script で書き換える
+
+--Task list
+
+       task_list にオブジェクト生成するコードを入れる
+       オブジェクトが生成されてしまえば、普通に扱える
+
+       task 実行中にコードが追い出されることはない
+           現在実行中のコード
+           次にロードするコード
+       の二つは必ずメモリ上にある
+
+
+--SceneGraph と Rendering Engine
+
+      SceneGraph -> SceneGraph
+      SceneGraph -> Polygon
+      Polygon -> Span Pack
+      Span Pack を Texture を使って Rendering
+
+      これらを大きく並列に実行する
+      Rendering は細かく並列に実行する
+
+--SceneGraph と Rendering Engine
+
+1 dot 1 dot SPUが書いていく
+
+<td><img src="photo/rendering.png" alt="rendering" ></td>
+
+--Rendering Task
+
+SG2PP
+	SceneGraph を操作後、ポリゴンに変換し PolygonPack (ポリゴンの集合)を生成する
+PP2SP
+	ポリゴンの中から、Span (ポリゴン内にあるx軸に水平な線分) を抽出し、 SpanPack (Span の集合)を生成する
+DrawSpan
+	Span を使って 1 ラインずつ FrameBuffer に描画していく
+
+
+
+--Demo されている Chain
+
+      相互制約が非常に大きい物理シミュレーションの例
+      非ホロノミック系なので、単純な積分では力学を決定できない
+      SPU上で、すべての要素を同時に計算する必要がある
+          (あまり並列計算向きではない...ベクトル向き)
+
+(地味です...)
+
+
+--まとめ
+
+Blender/Linux/Cerium を用いたオープンソースなゲームフレームワーク
+
+SceneGraphを作れば、move/collision を記述するだけで並列に実行される
+
+ソフトウェアレンダリングなんで、なんでも自分で書ける
+
+--将来的には、
+
+	C++ やめたい。悪いことばかり。メモリ食い。
+
+	CbC (Continuatin based C)で書き直す予定。
+
+	Cell は、やばそうなので、新しい並列アーキテクチャとか。
+
+	Open Scene Graph, Open/CLとの関係とか。
+
+
+
+