/**/

チュートリアル 42:
Slab: GPU上でのデータ処理

この前のチュートリアルでは、3Dオブジェクトに対して追加のシェディングモデルを適用するために、グラフィックプロセッシングユニット(GPU)上で、カスタムシェーダがどのように実行されることが可能かを見てきました。頂点プロセッサおよびフラグメントプロセッサは、本質的に 3D ジオメトリをレンダリングするために設計されているため、少しの工夫で、これらのパワフルな実行ユニットによって任意のマトリックスデータセットを操作させ、イメージプロセッシングや同様なその他の処理を行うことが可能です。「すでに、任意のマトリックスデータセットの処理をCPU上でJitter マトリックスオペレータ(MOPs)によって行っている場合、なぜ、その処理のためにわざわざグラフィックカードを使うなどという馬鹿げたことをする必要があるのですか?」と疑問に思うかもしれませんが、その答えは「処理の速さ」です。

動作環境:このチュートリアルをすべて体験するためには、プログラマブル・シェーダをサポートするグラフィックカード(例えば、ATI Radeon 9200、NVIDIA GeForce 5000シリーズ以降のグラフィックカード)が必要になります。また、グラフィックカードのOpenGLドライバを利用できる最新のものにアップデートしておくことを推奨します。これは、Macintosh では、最新のOS アップデートによって提供されます。また、PC の場合は、グラフィックスカード、あるいはコンピュータの製造会社から得ることができます。

パフォーマンスに関する最近の傾向

CPU のパフォーマンスは、半世紀に渡って、多かれ少なかれムーアの法則(訳注*)に基づいています。これはCPU の性能が18ヵ月毎に2倍になるというものです。しかし、GPU のアーキテクチャはCPUのように柔軟性を必要とせず、本質的に並列処理が可能(すなわち、複数のピクセルはお互いに独立して計算することが可能)なため、効率化が進められてきました。その結果、時によっては6ヶ月ごとに2倍になるくらい、その性能は非常に速いスピードで向上しています。この傾向は「ムーアの法則の3乗」と言われるほどです。

訳注 : 「ムーアの法則」はintelの創立者の一人 Gordon Moore による「シリコンチップに搭載できるトランジスタの数が一定の年月の間に2倍になる」というもの。1965年当時は「1年で2倍」、1975年終わりには「2年で2倍」、1997年には「18ヶ月で2倍」と変化している。

これを書いている時点では、ハイエンドのコンシューマ向けグラフィックスカードは、最高で8つの頂点パイプライン(vertex pipeline)と24のフラグメントパイプライン(fragment pipeline)を持ち、それらは並列処理が可能です。そして、フルフレームレート、DVレゾリューション(解像度)において数十の画像処理エフェクトを実行することができます。さらにHDレゾリューションイメージをフルフレームレートで処理することさえ始まろうとしています。ここ最近の傾向を見る限り、GPU は CPU より速いスピードで性能が向上し続けるでしょう。

最初に

・Jitter Tutorial フォルダからチュートリアルパッチ 42Slab-comparisonCPU.pat を開いて下さい。qmetro オブジェクトに接続されたトグルボックスをクリックして下さい。パッチの下方にある jit.fpsgui オブジェクトに表示されている値によるパッチのパフォーマンスに注目して下さい。

・パッチを閉じ、Jitter Tutorial フォルダから 42jSlab-comparisonGPU.pat を開いて下さい。qmetro オブジェクトに接続されたトグルボックスをクリックして下さい。jit.fpsgui のパフォーマンスに注目し、CPU バージョンで先ほど見た値と比較してみて下さい。

このパッチは特に何かの仕掛けがあるわけではありません。単に、ノイズ(char のランダムな値)による640×480 のマトリックス上で加算と乗算を行っているものをカスケード(直列)に接続したものです。片方のパッチではこの演算をCPU で実行し、もう片方は GPU で実行しています。どちらの例もノイズはCPU で発生させています(負荷がかかっています)。2つのパッチの結果として表示されるものは同じになるはずです。しかし、あなたが最近のグラフィックカードを持っているならおそらく気づいたのではないかと思いますが、グラフィックスカード (GPU)上で実行した場合に実行速度は非常に速くなります。ここでは、まさに、データセットに対していくつかのシンプルな数値演算を行っているのであるという点に注目して下さい。そして、この同じテクニックは、グラフィックカード上で任意のマトリックスデータセットを処理するために使うことができるということを覚えておいて下さい。


CPU(左)とGPU(右)によって処理されたノイズ

シェーディングモデルとは?

前のチュートリアルと異なり、ここでは、ライティングやマテリアルのプロパティに基づいた3D ジオメトリとして表現されるようなものは何もレンダリングしていません。その結果、これはすでに見てきたシェーダと同じものとは全く思えないでしょう?。実際には、私たちはここでも同じ頂点プロセッサとフラグメントプロセッサを使っています。しかし、それはテクスチャ座標のピクセルが、出力バッファのピクセル座標へのジオメトリマップに対して適用されるという非常にシンプルなジオメトリに対してです。ライティングとマテリアルの演算の代わりに、フラグメントプロセッサ内部の個々のピクセルに対して任意の演算を実行することができます。このように、私たちは、CPU でマトリックスを処理する Jitter オブジェクト(Jitter MOPs )と同じように、シェーダプログラムを使うことができます。

・Jitter Tutorial フォルダの中の、42jSlab-compositeDV.pat を開いて下さい。一番左の qmetroオブジェクトに接続されている toggle をクリックして下さい。

・dvducks.mov 、dvkite.mov というファイル名を含んだメッセージボックスをクリックして2つのDVムービーをロードし、それぞれに対応する metro オブジェクトをオンにして再生させて下さい。

・一番上の jit.gl.slab のインスタンスに接続されている ubumenu オブジェクトから、好みの合成オペレータをロードして下さい。


“difference”オペレータを使って、GPU 上で合成された UYVY DV フッテージ

うまくハードウェアが動作を維持できれば、2つの DV ソースをGPU 上でリアルタイムにミキシングした状態になっています。2つの jit.qt.movie オブジェクト、および一番上の jit.gl.slab オブジェクトが、それぞれ、uyvy にセットされた colormode アトリビュートを持っていることに気づくと思います。チュートリアル49:カラースペース(色空間)で述べるように、これは jit.qt.movie オブジェクトに対して、DV フッテージを、彩度を減じられた(color-reduced) YUV 4:2:2 データでレンダリングするよう指示し、jit.gl.slab オブジェクトに対して入力されるマトリックスをこの形として解釈するよう指示するものです。DV は 彩度を減じられた YUV フォーマットで最適化されているため、uyvy データを使ってDV フッテージの復元をより効果的に行うことができます。uyvy データは、ARGB データが使用するメモリの2分の1程度までしか使わないため、グラフックカードへのメモリ転送をより効率的に行うことができます。

それでは、このチェインにいくつかの処理を追加してみましょう。

・パッチ下部の2つの jit.gl.slab のインスタンスに接続されている、read cf.emboss.jxs および read cc.scalebias.jxs と書かれたメッセージボックスをクリックして下さい。

・2つのエフェクトのパラメータを変更するための、右側のナンバーボックスを操作して、これらの2つのエフェクトを調整して下さい。


GPU上での追加の処理

どのように動作するか?

jit.gl.slab オブジェクトがこのマジックを管理しているのですが、では、これは一体どのように動作しているのでしょうか?。jit.gl.slab オブジェクトは、jit.matrix または jit_gl_texture メッセージを入力として受け取り、それを、シェーダを適用されたこのシンプルなジオメトリをレンダリングするための入力テクスチャとして使います。そして、その結果をもう1つのテクスチャの中へキャプチャし、それを jit_gl_texture <texturename> というメッセージとして次へ送ります。jit_gl_texture メッセージは、jit_matrix メッセージと同様に働きますが、これはメインシステムメモリに存在するマトリックスを表すのではなく、グラフィックハードウェアのメモリに存在するテクスチャイメージを表しています。

合成されたビデオを最終的に表示するためには、jit.gl.videoplaneオブジェクトが使われています。このオブジェクトは jit_matrix または jit_gl_texture メッセージを受け取り、その受け取った入力を平面ジオメトリ(planaar geometry)のテクスチャとして使うことができます。これは、jit.gl.gridshape のような他のオブジェクトへ自由に接続することができるため、例えば、jit.gl.gridshape に接続して、球面上へのテクスチャリングを行うことも可能です。

VRAM からRAM への移動

jit.gl.slab オブジェクトの間で名前によって渡される jit.gl.texture のインスタンスはグラフィックカード上に存在するリソースを参照します。このことは、jit.gl.videoplanejit.gl.gridshape のような3D ジオメトリ上にテクスチャの最後の適用が行われる場合には良い結果をもたらしますが、このイメージを CPU ベースのプロセッシングチェインで利用したいと思う場合、あるいはイメージやムービーファイルとしてディスクに保存したい場合にはどうでしょうか?そのためには、これをシステムメモリに送り返す方法が必要になります。jit.matrix オブジェクトは jit_gl_texture メッセージを受け取り、呼び出されたテクスチャをリードバック(読み戻し)することができます。これは、テクスチャデータをグラフィックカード (VRAM)からメインシステムメモリへ送ることによって行われます。

・Jitter Tutorial フォルダの中の 42jSlab-readback.pat を開いて下さい。一番左の qmetroオブジェクトに接続されているトグルボックスをクリックして下さい。前のパッチで見たように、パッチの右側で、メッセージボックスをクリックしてムービーを読み込み、metro オブジェクトをスタートさせて下さい。


GPU からマトリックスを読み戻す

ここでは、イメージは jit.gl.slab オブジェクトによって GPU 上で処理され、jit.matrix オブジェクトに、jit_gl_texture <texturename> メッセージを送ることによって RAM に再びコピーされています。この処理は、一般的に、データをグラフィックカードに送る場合ほど速くはありません。また、リードバック(読み戻し)の場合、彩度を減じられた(chroma - reduced )UYVY フォーマットもサポートされません。しかし、GPU が処理のかなりの分量を実行している場合、CPU から GPU へ、そして読み戻しのための転送が生じるとしても、このテクニックによって、CPU 上で同じ演算処理を行うより速く実行することができます。最近の世代の GPU ではリードバック(読み戻し)の性能が向上しているという点にも注目する必要があります。特に、PCI-e ベースのグラフィックスカードは、一般的に、AGP ベースのグラフィックカードに比べて、より良いリードバックの性能を持っています。

まとめ

このチュートリアルでは、jit.gl.slab オブジェクトを利用して、GPUを使った汎用データ処理を使う方法について説明しました。イメージプロセッシングに焦点をあてて説明しましたが、同じテクニックは任意のマトリックスデータセットに応用することができます。彩度を減じられた(chroma-reduced)uyvy データを使うことによるパフォーマンスに関する話題についても触れ、同様にGPU から CPU へイメージをリードバックする方法についても説明しました。