view presen/osc2009.html @ 10:2ee81742a961 default tip

presetation
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 26 Sep 2009 17:03:53 +0900
parents c161dcb3d43f
children
line wrap: on
line source

<html>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<title>2009-09-26 (土)   Cerium を用いた PS3 でのゲームの作り方</title>
<!-- metadata -->
<meta name="generator" content="S5" />
<meta name="version" content="S5 1.2a2" />
<meta name="author" content="Eric A. Meyer" />
<meta name="company" content="Complex Spiral Consulting" />
<!-- configuration parameters -->
<meta name="defaultView" content="slideshow" />
<meta name="controlVis" content="hidden" />
<!-- style sheet links -->
<link rel="stylesheet" href="ui/default/slides.css" type="text/css" media="projec
tion" id="slideProj" />
<link rel="stylesheet" href="ui/default/outline.css" type="text/css" media="scree
n" id="outlineStyle" />
<link rel="stylesheet" href="ui/default/print.css" type="text/css" media="print" 
id="slidePrint" />
<link rel="stylesheet" href="ui/default/opera.css" type="text/css" media="project
ion" id="operaFix" />
<!-- S5 JS -->
<script src="ui/default/slides.js" type="text/javascript"></script>
</head>
<body>

<div class="layout">
<div id="controls"><!-- DO NOT EDIT --></div>
<div id="currentSlide"><!-- DO NOT EDIT --></div>
<div id="header"></div>
<div id="footer">
<h1>2009-09-26 (土)   Cerium を用いた PS3 でのゲームの作り方</h1>
<h2></h2>
</div>
</div>

<ol class="xoxo presentation">

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