NVDA情報局(フラグ)

投資家目線でNVDAを買い煽るためのメモです

GPUのお勉強①

www.4gamer.net

 


(部分引用)

GPU(Graphics Processing Unit)はもともと,3Dグラフィックスを描画するための専用ハードウェアとして誕生している。すなわち,3Dグラフィックスで同時多発的に発生する,頂点の座標変換や,ピクセルの陰影処理などにおけるベクトル計算を,CPUよりも高速に処理するためのプロセッサ、つまり「3Dグラフィックスアクセラレータ」だったのである。

 

 初期のGPUは,3Dグラフィックス処理において頻発する,典型的なベクトル計算に特化したハードウェア設計がなされた。そのため,「比較的シンプルなベクトル演算器を複数個実装する」形態からスタートしている。

 

その後,3Dグラフィックスの表現力の強化が望まれるにつれ,シンプルなベクトル演算器だった演算コアは,「より高度なソフトウェアを実行できるような,汎用プロセッサ的な機能」を備え始めていく。

 

また,演算コアの数自体も,製造プロセス世代が新しくなるにつれ,増加の一途を辿っていった。

 

そして,GPUの汎用プロセッサ化”に,決定的な影響を与えたのが,プログラマブルシェーダ(Programmable Shader)だ。GPUの各演算コアにおけるプログラマビリティの向上は,プログラマブル・シェーダ仕様(Shader Model,以下SM)バージョンアップの歴史に相当すると述べても,過言ではない。

 

プログラマブルシェーダの歴史は,DirectX 8時代におけるSM1.xの登場から始まる。GPUの演算コアで――プログラム長に制限はあったものの――自由にソフトウェアを実行できるようになったのだ。

 

DirectX 9のSM2.0では浮動小数点演算に対応し,同じくDirectX 9のSM3.0では,より高度な条件分岐を伴ったソフトウェアを実行できるようになった。

 

Windows Vistaで導入されたDirectX 10世代のSM4.0では,さらなるプログラマビリティの向上と,プログラム長の(事実上の)撤廃が行われ,CPUに迫る複雑なソフトウェアロジックを実行できるようになっている。

GPGPUという概念が起こったのはDirectX 9時代となる2003年ごろからで,「3Dグラフィックス処理だけでなく」,「それ以外のソフトウェアも,GPUアクセラレーションできないか」という研究が発端だった。

 

2004年8月には,世界初のGPGPU研究報告学会「GP2」(Workshop on General Purpose Computing on Graphics Processors)が開催されたが,本学会では発表者達が,GPGPUの抱えている問題を厳しく指摘していたことを筆者は印象的に記憶している。

 

ノースカロライナ大学のFrederick P.Brooks,Jr.氏はGPU仮想メモリを取り扱えないことに苦言を呈し,並列コンピュータを用いた原子レベルでの物理シミュレーションを研究しているLawrence Livermore National LabのMark Seager氏は,GPUが例外処理能力に乏しいことを問題視していた。

 

あれから4年以上。2009年のGPGPUでは,当時指摘された弱点をほぼ克服してきており,様相もかなり異なっている。

 

もともとCPUにとって重荷だった3Dグラフィックス処理のアクセラレータとして登場したGPUは,CPUの得意分野であるはずの汎用ソフトウェア領域にまで踏み込もうとしているのだ。


なぜGPGPUなの? なぜCPUじゃダメなの?

というわけで,GPGPUを定義づけるなら,「高機能になったGPUを,3Dグラフィックス処理以外の汎用目的で使うこと」になるのだが,もう少し「GPU=グラフィックスカード」的な立ち位置から説明すると,「GPUの,ディスプレイに画像を表示する機能は使わず,計算したり,メモリの読み書きをしたりする機能だけを活用すること」といったイメージになる。

ただこの場合,「計算してメモリを読み書きするだけなら,CPUでもできるじゃん」と思う人がいるかもしれない。

 

だが,冷静になって数えてみると,一つのCPUに実装されているベクトル演算器の数は,多くても数基程度。これに対してGPUでは,少なくとも十数基,ハイエンドGPUでは数百基内蔵されており,クロックの違いなどを考慮しても,ざっくり10倍程度は,GPUのほうが高速だ。

 

メモリシステムも,DDR3トリプルチャネルメモリコントローラを内蔵したCore i7でさえ192bit×1066MHzで帯域幅25.6GB/sなのに対して,ハイエンドGPUならGDDR3の512bit×2GHzで,100GB/sを大きく超える帯域幅を確保している。

 

これはどういうことか。CPUでは高速に処理するのが難しい,「超並列ベクトル計算」「大局的なデータ処理」を,GPUなら処理できるということになる。言い換えれば,これらこそがGPGPUにふさわしいテーマ,というわけだ。

 

 

例えばビデオのトランスコード処理も,超並列ベクトル計算や大局的なデータ処理という,GPUの特性を生かせるから,GPGPUでの実装が行われたのである。

 

では,超並列ベクトル計算や大局的なデータ処理というのは,ゲーム分野だとどのようなテーマで活用され得るのか。イメージもしやすいのが,物理シミュレーションとAI(Artificial Intelligence,人工知能)だ。


ゲームで役に立つGPGPU(1)~物理シミュレーション

大量の3Dモデル同士が衝突したりするシミュレーションを実装する場合,どの3Dモデルが別のどの3Dモデルと衝突しているのかを,全モデル同士,総当たりの組み合わせで計算する必要がある。まあ,実際には最適化が行われるので,文字どおりの「総当たり」にはならないが,計算量が膨大になることだけは間違いない。

剛体の衝突物理シミュレーションは言うに及ばず,オブジェクトが“自ら”変形することで,さらに複雑度が増す柔体物理シミュレーション,水面の動きを表現するための波動物理シミュレーション,液体や煙などの動きを再現するための流体物理シミュレーションなども,GPGPUにはおあつらえ向きなテーマだとされている。

 

また,GPGPUをキネマティックス(人体運動学)シミュレーションに応用して,モーションキャプチャに頼らずに自然な人体のアクションを再現/生成しようとする動きもある。

 

ただゲームにおけるGPGPUを活用した物理シミュレーションは,当面の間,爆発で生じる破片や爆煙の動き,水面の動きなどといった,ゲーム進行の本質にあまり関わらない「効果物理」用途が中心となると思われる。

 

実際,GPGPU(※具体的には後編で述べるNVIDIAの「CUDA」)に対応を表明している「Mirror's Edge」や,「Bionic Commando」でも,実装されているのは効果物理だけだ。

多くのPCにGPGPUが浸透すれば,ゲームシステムの根幹に高度な物理シミュレーションが導入され,ゲームプレイ自体に新しい変革がもたらされるようになるかもしれない。

 

実際,(GPGPUの実例ではないが)昨今,マルチコアCPUが大前提となったことで,EAの「Mercenaries 2: World in Flames」やTHQの「Red Faction: Guerrilla」など,高度な物理シミュレーションの形態,「ノンリニア破壊」をゲーム性に組み込んだタイトルも出始めている。

 

GPGPUが大前提となる時代がやってくれば,これよりもさらに高度な物理シミュレーションをゲームシステムに組み込んだものだって,登場してくる可能性があるのだ。

 

(後編) 

最初期のGPGPUでは,GPGPUのための開発プラットフォーム」が用意されていなかった。そのため,GPUを3Dグラフィックス処理以外で使うに当たっても,DirectXなりOpenGLなりといった,「標準的な3DグラフィックスAPIとその関連ライブラリ」を“普通に”利用し,グラフィックスを描画するプロセスを活用しなければならなかったのだ。

 

具体的には,
処理したい入力データをテクスチャに入れ込む
シェーダプログラムで演算を実行する
演算結果をフレームバッファ(=レンダーターゲット)へ出力する

言ってしまえば,「汎用計算を『3Dグラフィックス処理である』と偽装して、GPUをだまして処理させる」形態だった。

 

データをGPGPUで処理するための決まった手段がなかったので,GPUに,テクスチャとして扱わせたというわけである。

 

 「GPUが取り扱うテクスチャ」というと,通常は画像がイメージされるが,これを“データ形態”として捉えた場合には,格子(Grid)状に展開されたデータ列と見なすことができる。

 

つまり「行列代数の計算」「画像分析処理」「波動力学流体力学」のような,2次元のグリッドデータ形式で処理しやすい物理シミュレーションなどが適していることになる。

 

音声データのような1次元的なデータストリームも,2次元的なグリッドデータとして格納してやることで,GPGPU向きの処理系にすることは可能だった。

ただ,この「GPUに偽装3Dグラフィックス処理をさせてGPGPUをさせる手法」には欠点というか,限界があった。

 

その理由は大きく分けて二つある。一つは,CPUと違って,GPUには明らかにされない部分が多く,どのようにプログラムすると最大のパフォーマンスが得られるのかが分かりにくかったという点だ。

 

一例を挙げると,NVIDIAの「GeForce FX」では,ブロックダイアグラムすら公開されず,使えるはずの機能が使えなかったり,さらには理論性能とほど遠い性能しか出なかったりしたことで,開発者達の頭を相当悩ませた。ソフトウェア制作において最適化というのは重要なテーマなのだが,ブラックボックスが当たり前のGPUではこれが難しかったのだ。

もう一つは,GPGPUソフトウェアの設計&実装の手法が,CPUのそれと,かなり異なったものだったという点である。

 

大量なデータに対して処理を行うことを考えてみよう。CPUの場合,プログラムカーネルをFORループで括ってデータインデックスを動かし,処理対象のデータを一つ一つ切り換えるように実行させる。

 

これに対して最初期のGPGPUでは,シェーダユニットにプログラムカーネルを置いて,ここにデータを与えてやると,そのデータサイズに合わせて,自動的にプログラムカーネルにたいして、データ入力が実行されるようになっていたのだ。

 

GPUというその“生まれ”ゆえの特性から,プログラムカーネルは、入力データを書き換えられず,処理結果は入力データとは別の領域に格納され,なおかつプログラムカーネルは,直前の処理結果であっても,「今取り扱っているデータ」以外の参照を行えない。

 

そのためGPGPUでは,一つ一つのデータ処理を行うに当たって,ほかのデータとの依存関係に配慮した特別な処理を,CPU用ソフトウェアと同じように盛り込むのは難しかった(※マルチパスで実装すれば,不可能ではない)。

 

これらのことから最初期のGPGPUでは,「特定のGPUに向けて最適化したGPGPUソフトウェアは,別の世代のGPUや,別のメーカー製GPUで動作させるのが難しい」「CPU用のソフトウェアを,GPGPUへ単純に移植することはできない」という,二つの問題と向き合う必要があったのだった。

 

プログラマビリティが向上して高性能化したGPUで汎用プログラムが動かせる可能性は芽生えたものの,それを行うには,使う側に並ならぬ工夫と努力が求められていた,というわけである。


そんなGPGPU環境を改善すべく,まず取り組まれたのが,GPGPU向けの新言語開発だった。要するに,アルゴリズム(※問題を解決するための手順や手法。ここでは「GPGPU処理」とほぼ同義)をグラフィックスプログラムに偽装するテクニックが面倒だったから,ここをなんとかしようという動きが出てきたのだ。


初期のGPGPU言語としては「Sh」「Scout」「BrookGPU」といったものが挙げられる。

 

Brookだが,スタンフォード大学で開発されたこれも,C言語をベースに,ストリームデータを取り扱えるように拡張を施したような言語だ。

 

ストリームとは,大量のデータを1か所に溜め込んでから処理するのではなく,端から流しながら処理する方式を指す。データを流れ(ストリーム)として捉えて入出力を行うことは多くのプログラミング言語で行われているのだが,流れてくるデータを逐次,演算処理できるようにしたのがストリーム処理言語である。

 

Brookにおいて,ストリームデータは「<>」で定義することができ,ストリームデータの大きさ(=長さ)が異なる物同士の計算のつじつま合わせも行ってくれる。また「BrookGPU」としてGPUへの移植が行われ,現状ではそちらが主流となっているため,あたかもGPUをストリーミングプロセッサのように扱えるようになるのが特徴だ。

 

なおBrookは,その後,当時のATI Technologiesによって仕様拡張が行われて「Brook+」となり,現在に至るまで,AMDGPU向けGPGPUプログラミング言語の標準的な位置付けとなった。
 

初期のGPGPU言語は,最も普及していたプログラミング言語である,C言語をベースにした。C言語の“上”に,ベクトルデータやストリームデータを簡単に取り扱えるような,拡張概念を導入したわけだ。

 

より具体的に言い換えるなら,「CPU向けのC言語だと,一つの命令で取り扱える入力データと出力データは1個ずつが基本。これに対して初期のGPGPUプログラミング言語では,データを塊(かたまり)とし,まとめて入出力できるように拡張された」ことになる。

 

初期のGPGPUプログラミング言語達は,GPGPU環境を大きく改善はした。ただ,制作されたGPGPUソフトウェアは動作対象GPUの仕様に強く依存してしまっていたため,開発した環境と同等のシステムでしか動作しないようなケースが多く,GPGPUソフトウェアを多くのユーザーで共有するのが難しかった。

 

こうした業界の要望にいち早く呼応したのは,GPUメーカー巨頭の1社,NVIDIAである。2006年11月,「GeForce 8800 GTX」の発表に合わせる形で,NVIDIAは,GeForce 8以降の同社製GPUで、シームレスかつスケーラブルな動作/実行を保証するGPGPUプラットフォーム「CUDA」(Compute Unified Device Architecture)を正式発表したのだ。

 

CUDAを一言でまとめるなら,「NVIDIAGPUを汎用ベクトルプロセッサとして活用するための,ハードウェアとソフトウェアによるトータル,かつロイヤリティフリーな環境」といったところ。

 

ここでいう「ハードウェア」にはGeForce 8世代以降のGeForceと,ワークステーションGPUであるQuadroGPGPU専用プロセッサであるTeslaが含まれる。

 

次に「ソフトウェア」だが,これはプログラミング言語「CUDA C compiler」(CUDA Cコンパイラ)を中核とした開発環境と, GeForce/Quadro/TeslaをCUDAプロセッサとして利用するためのドライバソフトを指す。

 

CUDA C compilerはその名のとおり,C言語をベースとしつつ,ベクトル型の編集を扱えるように,“変数の型”が拡張されている。

 

頂点やピクセルの都合,テクスチャの参照様式といった3Dグラフィックス的な概念から解放されている。ごくごく普通に変数や配列を宣言し,C言語でプログラミングが行えるようになっている。

 

GeForce 8シリーズ以降において,シェーダユニット「Streaming Processor」(SP)は8基1グループとしてまとめられる。さらに,8SPで共有される16kBの「Local Memory」(LM,共有メモリ)と「Instruction Unit」(IU,命令デコードユニット)と組み合わせた構成は,「Streaming Multi-Processor」(SM)として,処理系の一単位とされている

 

また,これらは「ロイヤリティフリー」なので,開発者は,開発したCUDAベースのGPGPUソフトウェア(以下,CUDAソフトウェア)を,自由に扱うことができる。

 

利用料がかからないということで,NVIDIAの競合他社――AMDIntel――が自分達のハードウェアでCUDAソフトウェアを実行させる仕組みを構築すること自体にNVIDIAは干渉しない。

 

しかしオープンソースではないため,実質的にはほぼNVIDIA製ハードウェア用ということになる。

 

というわけで,事実上の“NVIDIA製ハードウェア縛り”は存在するわけだが,開発者からすると,ターゲットとなるハードウェア(=GPU)の仕様を理解していなくてもいいというのは,CUDAが持つ最大のメリットとなる。

 

しかも,CUDAソフトウェアのパフォーマンスは,GPUの世代やモデルに応じてスケーラブルとなるため,開発者もプログラム側も,「動作対象となるGPUGeForce 8800 GTXなのか,『GeForce GTX 295』なのか,はたまた『GeForce 9100M G』グラフィックス機能統合型チップセットなのか」といったことを気にする必要がない。

CUDAの尖兵となるNVIDIA PhysX

CUDAでは,標準ライブラリとして,

線形代数ライブラリのBLAS

高速フーリエ変換FFT)といったものが用意される。

 

Cコンパイラで生成された実行オブジェクトは,CUDAドライバでマネージメントされつつ実行される仕様だ。

 

このとき,CコンパイラはネイティブなGPU命令コードを吐き出すのではなく,「PTX」と呼ばれる中間命令コードで出力される。そして,このPTXコードは,CUDAドライバを通じて,動作させるターゲットGPUの構成や世代に適したネイティブコードに変換されて実行されるようになっている。

 

将来的に新しいGPUが登場したときには,CUDAドライバの更新によって,その「新しいGPU」に対応したPTX→ネイティブコードトランスレータ(Native Code Translator)が用意され,互換性が維持されるというわけ。

 

CUDAドライバとネイティブコードトランスレータは,「GPUコアが何基稼働していて、何基のStreaming Multi-ProcessorでGPUカーネルコードを実行できるのか」を吟味して動作する。

 

これが,GPUの世代,あるいはGPUの同時稼働数が異なっても,CUDAプログラムの実行互換性が維持される仕組みの根幹技術である。

 

ところで,CUDAドライバはDirectX用やOpenGL用グラフィックスドライバとは別の,独立したドライバソフトウェアとなるが,グラフィックスドライバとは協調して動作できる。

 

つまり,GeForceシリーズのGPUを1基のみ搭載したPCで,3DグラフィックスのレンダリングとCUDAソフトウェアの実行を同時に行えるということだ。もちろん,限られたSMを両者が奪い合うので,それぞれのパフォーマンスは削がれることになるが。


この同時実行の例としてPCゲーマーに最も身近な存在といえるのが,「NVIDIA PhysX」(旧称:AGEIA PhysX,以下PhysX)である。NVIDIAは,物理シミュレーションミドルウェア開発元のAGEIA Technologiesを2008年2月に買収。2008年のうちに,ゲーム業界で広く活用されてきた物理シミュレーションライブラリ(≒ミドルウェア)であるPhysXを,CUDAで実装することに成功している。

 

Release 180世代のGeForce Driverでは,世代やモデルの異なる複数のGeForceを搭載した環境で,片方をPhysXアクセラレーション専用に割り当てる機能である,「SLI PhysX」が正式に採用された。

 

これにより,GeForce 8以降のGPUを搭載したグラフィックスカードで,使い古したものが手元にあれば,それをPhysX専用に割り当て,新しく購入したGeForce搭載グラフィックスカードは3Dグラフィックス処理に専任させるような使い方ができるようになっている。

 

NVIDIAにとってPhysXは,PCゲーマーにCUDAの有効性を認知させる尖兵的存在となっており,今後の展開が期待される。


ATI Streamで対抗するAMD

対するもう一つの巨大GPUメーカー,AMDだが,少なくともCUDAが立ち上がったタイミングにおいては,(NVIDIAほどには)GPGPUへ積極的に対応していく姿勢を見せていなかった。どちらかというと,3Dグラフィックス用途に注力した製品展開を行っていたように見受けられる。


そんなAMDGPGPU製品群にあって,最初に業界内外の注目を集めたのは,2007年11月に発売された「FireStream 9170」だった。これは「ATI Radeon HD 3800」(RV670)ベースの製品で,GPUベースのHPCプラットフォームとしては,世界で初めて倍精度64bit浮動小数点(FP64)演算に対応した製品である。

 

続いて2008年6月には,「ATI Radeon HD 4800」(RV770)をベースとし,やはりFP64演算をサポートした「FireStream 9250」をリリースしている。


ベースとなるGPUを示したように,FireStreamは,同世代のATI Radeon製品と同じGPUコアを採用しているが,「ATI Stream」という,いわば“GPGPUモード”で動作し,ATI Radeon製品では無効なFP64演算機能が有効化されるなどのアドバンテージを持っていた。

 

CPUメーカーでもあるAMDとしては,GPUを「高性能な汎用プロセッサ」として使えるGPGPUソリューションを民生向けに積極転用することは,自社CPU製品の首を絞めかねない可能性をもつと感じていたのかもしれない。

 

だが結果として,「一般ユーザー向けGPGPU環境の整備」に,NVIDIAと比べてAMDが消極的だったのは事実だ。

 

ただ,この流れは2008年後半に一変する。PhysXに始まり,ビデオデータのトランスコードなど,GeForceを利用したGPGPUアクセラレーション技術が具体性を帯びてきたことで,危機感を感じた……のかどうかは分からないが,2008年12月,ついにAMDは民生向けGPGPUプラットフォームの提供へと舵を切った。

 

それが,ATI Radeonにおける「ATI Stream」のサポートである。これにより,それまでFireStreamでしか利用できなかったGPGPUモードが,ATI Radeonからも利用できるようになった。

 

ATI Streamの実装は,CUDAとよく似ている。ハードウェアとしてのGPUを抽象化する層を挟み,上層に,高級言語プログラミング言語ミドルウェアやライブラリを置く構造だ。

 

物理シミュレーションに代表される,高度なリソースマネージメントとハイパフォーマンスが必要なライブラリやミドルウェアにおいては,AMDGPUのネイティブコードであるCTM(Close To Metal)相当で実装されるが,一般的なGPGPUソフトウェア開発者は,高級言語を使って開発することになる。


開発言語は,本稿の前半で触れたように,ほかのGPGPUプログラミング言語と同様,C言語をストリームデータ処理のために拡張し,新たな関数を追加したような仕様のBrook+が標準として提供される。

 

Brook+ベースのGPGPUソフトウェアは,このBrookコンパイラによって中間言語コードであるCALコードに変換され,ドライバに含まれるCALランタイムが,これをGPUネイティブコードに変換して実行する流れになっており,CUDAと本当によく似ている印象だ。
 

ハードウェア的なポテンシャルという点で,ATI StreamがCUDAに大きく劣っている部分はない。それだけに,GPGPUソフトウェアを開発してくれるソフトウェアデベロッパを,AMDがどれだけ支援できるかが,ATI Streamのカギとなるだろう。

 

Microsoftは「Direct3Dの拡張」という形でGPGPUをサポート

 

Microsoftにもさまざまな事情があったようで,GPGPUプログラミング言語の観点から研究をして「Visual Studio」のような開発ソフトウェアに統合しようとする動きがあったかと思えば,長きに亘(わた)わたって熟成が進められてきたマルチメディアコンポーネントDirectX」に統合させようとする動きもあったりして,優柔不断というか,フットワークが非常に重かったのだ。


ちなみに前者は,「Microsoft Accelerator」というプロジェクトになった。これは.NET環境でC#を使ってGPGPUプログラミングを行えるようにしようとするものだったが,2007年夏を最後に,アップデートが途絶えている。

 

一方,2008年に,突如として具体的な話が浮上してきたのが,後者,DirectXに統合させる動きである。その名も「DirectX Compute Shader」。日本法人であるマイクロソフトの資料では,「DirectX演算シェーダ」とあるので,これが和名となるようだ。


実装的な視点に立つと,「Direct3DGPGPU関連APIの追加を行い,シェーダプログラミング言語(HLSL)をGPGPUに対応させた」のがDirectX Compute Shaderということになる

 

DirectX Compute Shaderは,3Dグラフィックスのレンダリングを司るDirect3Dに統合される形で実装され,Direct3D上のリソース(※テクスチャ,レンダーターゲットなど)はすべて透過的に取り扱える。つまり,3Dグラフィックスと関係の深い処理や,映像処理に特化したGPGPU処理を実装するのに,DirectX Compute Shaderは向いていることになる。

 

あくまで「Direct3DGPGPUに対応させた」というスタイルなので,基本的な実行メカニズムは,GPGPU用プログラムをDirectX Compute Shaderプログラムとして実装し,これをGPUのシェーダユニットで走らせ,処理させたいデータをDirect3Dに入力して結果を得るといった流れ。

 

それでも,SPMD(Single Program,Multiple Data)のプログラミングモデルの実装に向いているのは確かなので,例えば群集シミュレーションのAI,大局的な物理シミュレーション処理,3Dグラフィックスのポストプロセスなどには向いているはずだ。

 

総じて,ゲーム向けGPGPUとしては必要十分なポテンシャルがある印象。おそらく,ビデオのトランスコード処理アクセラレーションにも対応させることができるだろう。

DirectX縛り”があるため,CUDAやATI Streamほどにはソフトウェア設計の自由度がなく,汎用性もやや限定される。しかしその代わり,Direct3Dのリソースを透過的に取り扱えるというメリットがある。ここが重要なポイントだ。

 

それは,この仕組みにより,Direct3Dレンダリングした3Dグラフィックスの後処理をDirectX Compute Shaderで行ったり,あるいはDirectX Compute Shaderで行ったシミュレーション結果をDirect3Dレンダリング素材として利用したりすることができるからである。もちろん,3Dグラフィックス処理とGPGPU処理の双方で取り扱うデータを共有しているので,面倒なバッファ間のデータ転送は不要。そのため,「3Dグラフィックスパイプラインで用いているアニメーション処理適用済みの3Dモデルを,DirectX Compute Shaderで実装している物理シミュレーションの衝突判定用に流用したりする」なんてことが可能となる。

また,「3Dグラフィックス処理の新しいメカニズムの実装にも,DirectX Compute Shaderが活用できるのではないか」,という期待もなされている。

 

その筆頭事例に挙げられているのが,「A-Buffer」の実装だ。A-Bufferとは,映画向けCGなど,オフラインレンダリングの世界ではすでに実用化されている技術で,半透明オブジェクトの描画に当たって順不同実行を容認する仕組みのこと。かねてからGPUへの実装が検討されていたが,専用ハードウェアロジックではなく,DirectX Compute Shaderの活用により,GPGPUソフトウェアの形で実装できるのではないかという,議論がなされてきている。


DirectX Compute Shaderを使えば,3Dグラフィックスとしてレンダリングした複数の映像フレームを,適応型の処理によって1フレームに合成するといったことも実現できるからだ。DirectX Compute Shaderは,現状のリアルタイム3Dグラフィックスレンダリングパイプラインを拡張する意味合いの目的でも,期待されているのである。


DirectX 11は,2009年に登場する見込みであり,対応GPUも2009年中に出てくると予想されている。Windows 7だけでなく,Windows Vistaにも提供され,さらにDirectX 10世代のハードウェアでも,DirectX Compute Shaderを利用できる仕組み(=リファイン版DirectX 10)が提供される予定だ。

 

つまり,2009年(の後半)以降,DirectX Compute Shaderは,多くのPCユーザーが利用できるようになる見込みなのである。

 

NVIDIAAMDGPUメーカーもDirectX Compute Shaderへの対応姿勢を見せているため,GeForceATI Radeonといった区別なく,DirectX Compute ShaderベースのGPGPU動作はサポートされることになる。単一のGPGPUソフトウェアを,メーカー不問のGPU環境下で透過的に動作できるようになるのだ。ゲーム向けGPGPUソリューションは「NVIDIAAMDか」の踏み絵を迫られていたが,DirectX Compute Shaderによって,ゲームデベロッパが一気に対応姿勢を見せてくることを期待できる。


オープンなGPGPUプラットフォーム,OpenCL

DirectXWindowsのマルチメディアコンポーネントAPIであり,動作する環境は,Windows,あるいはMicrosoftのプラットフォームに限定される。そのため,DirectX Compute Shaderが動作する環境も,Microsoftのプラットフォームのみとなる。

 

しかし,GPGPUという概念自体はもっと一般的なものである。そのため,特定のハードウェア/ソフトウェアメーカーの影響を受けず,かつ,移植性の高い規格の登場も望まれてきた。

これを受けて,2008年夏,コンピュータ関連企業の業界団体にして,標準プログラミングAPI策定を行っているKhronos Groupによって発表されたのが,「OpenCL」(Open Computing Language)だ。

 

Khronos Groupは,オープン仕様な3DグラフィックスAPIである「OpenGL」の規格策定も行っている。そのため,OpenCLについて,「Direct3DにおけるDirectX Compute Shaderのようなもの?」というイメージを抱くかもしれないが,コンセプトや実現様式が微妙に違う。

 

最大の違いは,OpenCLが,GPUだけを対象としているわけではないということだ。x86プロセッサやCellプロセッサといったCPU,あるいはDSP(Digital Signal Processor)のようなメディアプロセッサなどのプログラミングに対応するコンセプトを持っており,GPUに特化したDirectX Compute Shaderとは似て非なるものだといえる。

プログラミング言語C言語ベースで,CUDAやBrook+のような,並列プログラミング向けの仕様拡張が成されている。業務用や学術用途で使われることを想定して,IEEE 754(※浮動小数点数に関する表現と演算を規定した規格)準拠の,厳格な浮動小数点精度が規定される。

 

コンパイラが生成する命令コードは抽象化された中間コードになり,実行はGPU(≒ハードウェア)ごとに設計されたOpenCLドライバがネイティヴコードを吐き出して実行する仕組みだ。これはCUDAやATI Streamなどと同じだといえる。


OpenCLの拡張型C言語には,便利な関数等を収録したライブラリが提供されるが,物理シミュレーションや映像エンコーディングのような特定用途のための高機能関数やミドルウェア的なAPIは提供されない。あくまでOpenCLGPGPU向けのプログラミング環境であるため,策定される規格は基本的でローレベルなものに留まるようだ。

前述したように,OpenCLは,GPUだけではなくCPUやDSPにも対応するため,プログラムの実行のさせ方も特徴的で,OpenCLの「Platform Layer API」にて,「どのOpenCLプログラムをどのプロセッサで実行させるか」を割り当てられるようになっている。

 

例えばマルチコアCPUとGPUを両方搭載するようなシステムでは,それぞれに異なるOpenCLプログラムを実行させたり,あるいはCPUとマルチコアGPUに同一プログラムを実行させて並列度を上げ,さらなるパフォーマンス向上を狙ったりといったことも可能だ。

 

さらにOpenCLでは「Runtime API」で,各OpenCLプログラムの実行制御や処理結果の制御も行える。OpenCLは,それ自体がGPGPUコンポーネントAPIになっているという感じで,DirectX Compute Shaderというよりは,構成自体がCUDAやATI Streamに近い印象である。

 

ただし,DirectX Compute Shader的な部分もある。それは,OpenCLが,3DグラフィックスAPIOpenGLと同時に,協調動作できる点だ。

DirectX Compute ShaderはDirect3Dに統合されているのに対して,OpenCLはその実装上,OpenGLから独立している。しかし,OpenGLOpenCLを結ぶInter-API(内通API)が実装されており,OpenGLOpenCLはお互いにリソースを共有できる設計となっているのだ。

 

具体的にはテクスチャ,レンダーターゲットの各種バッファなどを共有でき,OpenGLからOpenCL向けの各種オブジェクトの生成も行える。よって,「OpenCLで実行したシミュレーション結果」の頂点データやテクスチャデータを,OpenGLにて3Dグラフィックス描画に利用したり,あるいはOpenGLの描画結果をOpenCLでポストプロセス処理したりできるわけである。

 

統合されていないOpenGLOpenCLが,あたかも統合されているかのように,両者を統括的に扱えるという点では,DirectX Compute Shaderとよく似ている。

 

もともとOpenCLApple主導で提唱が行われた経緯があるのだが,AppleとしてはこのOpenCLを,2009年内にリリース予定となっている次期Mac OS,「Mac OS X Snow Leopard」に実装させたい思惑がある。実のところ,OpenCLはその提唱がなされたばかりであり,仕様の確定は2009年中頃とスケジュールされているのだが,Mac OS X Snow Leopardの登場は2009年6月と噂されているので,OpenCLの仕様確定も,このあたりになるのではないだろうか。


どうなる? GPGPUプラットフォームの覇権争い

他勢力に先行してGPGPUへの対応を進めてきただけのことはあって,現時点におけるアプリケーションの対応度という点では,NVIDIAのCUDAが一番だ。

 

とくにPCゲーマー的な観点からすると,一世代前のGeForce搭載グラフィックスカードを,「そのままPhysXアクセラレータとして継続利用できる魅力」は大きい。今後,PhysX対応タイトルの数を順調に拡充できれば,一般ユーザー向けGPGPUプラットフォームとして,しばらくの間,競合を圧倒し続けるだろう。

 

対するAMDの,「ATI StreamによるATI Radeonサポート」は,CUDAに対するカウンターパンチの意味合いが強く,一般ユーザーに向けたアプリケーションのアピールがまだまだ弱い。少なくとも,PCゲーマーにATI Streamの優位性を訴えるには,ATI StreamベースのHavokアクセラレーション実装が不可欠と思われる。

 

やや妄想じみた話をすると,GeForcePhysXATI RadeonでHavokのアクセラレーションができるようになれば,「GeForceATI Radeonを1台のシステムに両方搭載し,ゲームタイトルごとに3Dグラフィックス描画と物理シミュレーションのアクセラレーションを切り替える」なんて話だって出てくるかもしれない。

 

ただ,本音を言えば,プロセッサメーカーによる“縛り”のないGPGPUプラットフォームこそが理想なのも確かだ。その点で,DirectX Compute ShaderやOpenCLの動向は,最重要視していかなければならない。

 

これらにはNVIDIAAMDの両社とも対応を明言しているので,特定メーカーの動向に引きずられたくない多くのアプリケーションベンダーは,この二つの登場を待ちわびている状況だ。

 

OpenCLMacintoshや組み込み機器での活用がメインとなる見込みなので,Windows環境下では,やはりDirectX Compute Shaderが本命ということになる。

 

DirectX Compute ShaderにもDirectXという“縛り”はある。CUDAやATI Streamといった,ピュアなGPGPUプラットフォームと比較すれば自由度は落ちるが,それでも,Windows環境標準というのは大きな強みで,強力な勢力となるはずだ。

 

したがって,長期的にはGeForceATI Radeonかといった“踏み絵”なしに,GPGPUの恩恵を受けられる未来が見えているわけだが,一方でNVIDIAAMDの立場からすると,自社のGPGPUプラットフォームをいかに訴求していくかが,競合に打ち勝つためのポイントになってくる。

 

GPGPUベースの物理シミュレーションなり,動画エンコードのパフォーマンスなりで,「DirectX Compute Shaderで実装するよりも,うちのGPGPUプラットフォームで実装するほうがパフォーマンスは高くなる」といったアピールは,いずれ必ず行われることになるだろう。

 

image

CPUとGPUの違い

 

 image

CPUプログラムとGPUプログラムの違い

 

image

データ間の相互依存性に配慮した処理は,最初期のGPGPUだと難しかった

 

 

image

2006年,NVIDIAは自社ハードウェアでの動作を保証するGPGPUプラットフォーム「CUDA」を発表した

 

image

CUDAの実装概念図。アプリケーションはランタイムの中間コード化され,最終的なGPUネイティブなCUDAソフトウェアの実行マネージメントはドライバが行う

 

 

image

 

 

GeForce 8シリーズ以降において,シェーダユニット「Streaming Processor」(SP)は8基1グループとしてまとめられる。さらに,8SPで共有される16kBの「Local Memory」(LM,共有メモリ)と「Instruction Unit」(IU,命令デコードユニット)と組み合わせた構成は,「Streaming Multi-Processor」(SM)として,処理系の一単位とされている

 

image

CUDAソフトウェアのコンパイルフロー。PTXはCUDAドライバ側のネイティブコードトランスレータにより,そこで初めてネイティブなGPU命令コードに変換されて実行される

 

 

 

 

image

CUDAのソフトウェアスタック

 

image

 

PhysXのソフトウェアスタック図。PhysX用CUDA Solver(CUDAソルバ,右下)の開発によって,PhysXGeForceによるアクセラレーションが可能となった。ちなみに「APEX」は「Applied PhysX Extension」の略で,PhysX SDK内の物理プリミティブを組み合わせて,複雑な物理イベントをオーサリングしたりする仕組みのこと。NaturalMotionは,モーション生成ミドルウェアの「euphoria」をAPEXでも実装している

 

image

ATI Streamでは,GPUハードウェアのネイティブな命令セットを抽象化するCAL(Compute Abstraction Layer)を持ち,ここがドライバ部分に含まれることになる

 

image

Microsoftは,Direct3DGPGPUに対応させるという選択をした

 

 

image

image

実装的な視点に立つと,「Direct3DGPGPU関連APIの追加を行い,シェーダプログラミング言語(HLSL)をGPGPUに対応させた」のがDirectX Compute Shaderということになる

 

image

 

image

DirectX Compute Shaderは,3Dグラフィックスレンダリングパイプラインの拡張目的にも使える

 

 

OpenCLOpenGLとの同時協調動作のサポート

 image

OpenCLのメモリモデル。各演算ユニットはプライベートなローカルメモリ領域を持ち,基本的にはここで処理をこなし,ほかの演算ユニットとの共有メモリを介して同調を取る。まるで,GPULarrabeeのブロックダイアグラムを見ているようだ