Mercurial > hg > Papers > 2010 > program-symposium
view 7.tex @ 0:a9fda18657b3 default tip
add
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 16 Dec 2009 10:05:04 +0900 |
parents | |
children |
line wrap: on
line source
\section{ Cerium Engine} Cerium Engine は、PS3 上のScene Graphの描画と変更によって 記述されたゲームを実行する Engine である。Task の生成を 管理する TaskManager, Task をScheduleする Scheduler, ソフト的なキャッシュを管理する MemeorySegment そして、 SceneGraph ライブラリ、 複数の Task で実行される Rendering Engine からなる。 C++ で記述されており、Mac OS X, Linux, PS3 上で同一の ソースで動作する。 SceneGraph は、Blender (Open Source な3D modeling Tool) から、Python Script を作って生成された XML である。 内部でも生成変更可能である。 SceneGraphのパラメータを変更することによりゲームが 進行し、それと同時に Pipeline 的に SceneGraphの描画を 行う。 Cerium Engine は、 Open CL とは独立に設計しているが、結果的には似たものになっている。 \subsection{ Task Manager} Cerium の Task は、型のない入力と出力を持つシンプルな関数である。 入力と出力は、Cell のDMAによって用意される。List DMAがあるので、 断片化されたデータを読み書きすることも可能になっている。 create\_task() で、HTask という構造を作成し、spawn()することで active queue に登録する。 Task は、番号で登録される。SPE と PPE では独立な番号を用いている。 手動による Overlay で、SPE 上のコードの入れ換えを行っているので、 ポインタで指定することは出来ない。Open/CL では、文字列で指定した プログラムを llvm に引き渡す形式だが、その点は異なる。 Cerium は、PPEのTaskと、SPEのTaskの二種類を持っており、それぞれ 別なキューで管理されている。さらに、Task の終了時に呼ばれる Task がある。 PPE Task は相互のDependencyを持ち、Dependency が満たされた時点で PPEまたはSPE上で実行される。 普通のOSと異なり、高度なスケジューリング は行われない。Task は十分小さく、基本的に preempt されずに 実行されるので、Round Robin などの工夫は不要である。通常の スレッドやプロセスとは異なる。 SPE上には最小限のSchedulerが存在している。SPE上では基本的にTask は生成しない。 SPE Task からはメインメモリは参照できないが、MemHash というLRU キャッシュが実装されている。しかし、特に構文的な制限があるわけではな く、PPE Task からはメインメモリ全域をアクセスすることが出来る。 一つのPPE Taskから生成されたSPE/PPE Taskは、まとめて投入される。 投入した Task は Cell の Mail を使って、SPE/PPE スケジューラに 伝えられる。終了した Task は、Dependency を解消し、Active に なった Task を Active Queue に移動する。 DMAは、Taskの中から起動することも可能になっている。PPE や、Mac OS X 上でも、DMAのEmulationを行っており、同じコードで、PS3、Mac OS X で動作させることが出来る。 HTask は、実行時は SchedTask と言う型のオブジェクトになる。 Cerium Engine に対する処理は、SchedTask へのメソッドで行われる。 \subsection{ Task 間の同期} Task はメインメモリ上にQueueを持っており、 {\small \begin{verbatim} task->wait_for(another_task) \end{verbatim} } という形で待ち合わせを行う。これは、task queue にwaiting queue を持つこととで実現されている。実際の実行は、Core 上で行われる。 Core から見たメインメモリはかなり遠いので注意が必要である。 {\small \begin{verbatim} task->set_post(post_task,in, out) \end{verbatim} } という形で、Taskの継続を指定することが出来る。継続のTaskでは、 DMA は行われない。主に、終ったタスクが書き出したデータの整理、 次のタスクの起動などに使われる。スケジューラの前に起動される ので、継続で接続された Task のチェーンは、見掛け上、シングル スレッドで実行される。 何もしないDummy taskを作り、それをwait\_for することにより、 同期を取るような手法が多用されることになる。これは、一種の バリアである。 taskの終了は Mail による通知であり、Singe Thread なTask Manager がMail 待ちループを持っていて処理する。 {\small \begin{verbatim} do { ppeManager->schedule(ppeTaskList); ppeTaskList = mail_check(waitTaskQueue); } while (ppeTaskList || spe_running >0); \end{verbatim} } つまり、wait\_for/set\_post はメインメモリ上の シングルスレッド Task として実行される。Task Manager を 複数のスレッド、あるいは分散したプロセスとして実装することも 可能だと思われるが、それが、wait\_for/set\_post の意味に どう係わるかは、かなり難しいと思われる。現状では、シングル スレッドが使いやすい。 \subsection{ Task} 一つの Task は、read/exec/write の三つに分解されて、 それぞれが、さらにパイプライン的に実行される。TaskManager は、それが可能なように、Core に複数のTaskの集合(TaskList) を投入する。 {\small \begin{verbatim} void Scheduler::run() { task1 = new SchedNop(); task2 = new SchedNop(); task3 = new SchedNop(); // main loop do { task3->write(); task2->exec(); task1->read(); delete task3; task3 = task2; task2 = task1; task1 = task1->next(this, 0); } while (task1); delete task3; delete task2; } \end{verbatim} } ここで、read/exec/write は Task の状態によって変わる ステートパターン用の仮想関数である。何もしないもの、 DMAの開始/待ち合わせ、次のタスクの取得、次の TaskList の取得などを行う。つまり、read/write は非同期で、 ほとんど待ち時間はないと想定されている。exec が 実際のユーザが定義したTaskの関数を呼び出す。 TaskList は、Core 側がEmptyになったのをMailでMain側に 知らせて、Main側から Mail によりTaskListへのポインタ を取得して、DMAにより転送を行う。これは一つのTask として実装されていて、上のパイプラインループの中で 実行される。 \subsection{ Memory Segment Manager } PPE上/SPE上のメモリは、MemorySegment によって管理されている。 これは、Hash access 可能な double linked されたメモリ領域 である。 これは、set\_global, get\_global によって、Core(SPE)上に 常駐する領域である。これは明示的に作成削除する必要がある。 Cerium Engine の性質上、ほとんどの処理は Pipeline Buffer 上で 行われる。つまり、 入力 MemorySegment から出力MemorySegment に書き出される Task の集合である。 MemorySegment は読むだけ、あるいは書くだけとなる。そうでないと、 Pipeline 実行時に途中でデータを変更されてしまうことになる。 Taskの実行時には、必ずメモリのコピーを伴うし、DMAのオーバヘッド のほとんどは隠されてしまうので、積極的にコピーする。メインメモリ は、SPEのLSに比べれば広大なので、倍量のメモリを取っても問題ない。 Texture や Polygon のデータ等、変更されない場合はコピーの必要はない。 必ず Copy を伴うので、細かく解放する必要がない。したがって、 常に Copying GC を行っているようなことになる。これは、Pool を 多用する Apache Web Server と同じような実装となる。