芸軌社株式会社
RSS 2.0

芸軌社公式ブログ

2013年1月23日(水)00:43(+0900)

GPUの性能(OpenGLによる3D地形グラフィックver0.05)

このエントリーをはてなブックマークに追加
OpenGLによる3D鏡山越え(Ver0.05)
OpenGLによる3D鏡山越え(Ver0.05)

以前の日記「OpenGLで3D鏡山越え(Ver0.01)」で紹介したOpenGLでの鏡山越え3Dですが、その後プログラムをいろいろと書き換え、バージョン0.05と称してバージョン0.01に比べ1桁強の描写スピードの向上が実現しました。手持ちのノートパソコン(Intel Celeron CPU B830 @ 1.80GHz × 2、内蔵GPU)で十分な精度での描写を行った場合、描写速度はv0.01の4fpsに対しv0.05は60fpsと、約15倍になっています。

v0.01とv0.05の速度の比較
v0.01とv0.05の速度の比較

GPUによる座標変換(頂点シェーダ)

さて、どうしてv0.05でv0.01に比べ1桁以上のスピードアップができたかというと、v0.05で何か特別な工夫をしたわけではなく、v0.01では通常の3DグラフィックでGPUを使うべき操作をCPUでやっていたために特に遅かったわけです(汗)

通常、3Dグラフィックは入力データ(頂点データ)から画面に出力するまでに、以下のような操作を行います。

  • 頂点データ→頂点シェーダ(GPU)→フラグメントシェーダ(GPU)→画面出力

ここでシェーダについて簡単に説明すると、頂点シェーダは入力した頂点データを実際に描写する視点に合わせて座標変換するプログラムで、フラグメントシェーダは変換した頂点から面を塗っていくプログラムです。グラフィックの描写に使われるGPUは簡単に言うとコア数の非常に多いCPUで、シェーダプログラムはGPUによって大規模並列計算され画面への描写データが用意されます。

ところで、GPUとCPUの違いを考慮に入れず描写速度を向上させることだけを考えると、画面描写のために用意する頂点データの数を減らすことが速度向上の鍵となり、このプログラムもv0.01、v0.05ともそのような視点に立って作っています。ここでv0.01では、描写のために用意する頂点を、まずは頂点変換をしてみて頂点が実際に画面の中に収まるかどうかで判断しており、結論から言うと最終的に必要な頂点が出揃った段階で既に頂点データの座標変換が完了しているという形になっていました(なお、変換する頂点数は最終的に必要な頂点数とあまり変わらないようにしている)。すなわち、v0.01での描写の流れは単純化すると以下のようになっていました。

  • 座標変換(CPU)→頂点データ→フラグメントシェーダ(GPU)→画面出力

通常であればGPUで行われるべき座標変換をCPUで行っていたために、描写に非常に時間がかかってしまったわけです。最小限の座標変換で必要な頂点を揃えるアルゴリズムは、(少なくとも私の用いたものは)容易に並列化できないものであり、GPUをフルに生かすには座標変換を行わずに必要な頂点を揃える必要がありました。座標変換無しで必要な頂点を判断する方法自体はそう難しくないのですが、それに付帯する細かい調整に苦労してしまい、完成までにけっこう時間がかかってしまいました(汗)

GPUでの画面描写にかかる時間

ついでに、今回のプログラム(v0.05)でGPUによる計算にどれくらいの時間がかかっているのか調べてみることにしました。まずはv0.01とv0.05を比較した時の描写精度で、通常の画面描写を実行した時とGPUを使わないで(画面を描写しないで)実行した時の速度を比べてみたところ、どちらも1フレームあたり約17ミリ秒(60fps)で、ほとんど(全く?)違いがありませんでした。これはGPUでの計算にほとんど時間がかかっていないというわけではなく、画面のリフレッシュレートか何かがボトルネックになっていてGPUでの描写時間がそれに埋もれてしまったものと推測されます。ボトルネックを避けるべく、とりあえず描写精度を4倍(描写頂点数:約12万点→約110万点)にしてみました。

v0.05のGPU計算を含む場合と含まない場合の速度比較
v0.05のGPU計算を含む場合と含まない場合の速度比較

結果は、GPU計算を行ったものが約50ミリ秒(20fps)、GPU計算を飛ばしたものが約33ミリ秒(30fps)でした。やたら切りのいいフレームレートなので、なおもリフレッシュレートか何かの効果が入っている可能性が高いですが、とりあえずGPU計算を加えることにより17ミリ秒ほど余計に時間がかかったことになります。描写頂点数が約110万点なので、単純計算で一秒あたり頂点変換を6億回行っていることになります(GPUとCPUが並列に動いていないと憶測で仮定して)。頂点変換一回あたり10回掛け算を行っているとすると、計算速度は約6GFLOPS。。。あれ、そう極端には速くない? いや、ここでは頂点シェーダしか考えてないけどフラグメントシェーダもあるし、その他にも多分いろいろあるから、実際は6ギガより1桁2桁多く計算しているのかも。

いずれにせよ、頂点変換をGPUで行うことにより、同程度の計算量のプログラムでも描写速度が10倍以上速くなることが分かりました。特に高性能というわけでもないと思われるCeleron内蔵のGPUでも大幅なスピードアップとなり、これを科学計算等にも生かしたいという気持ちも含めてGPUの性能を身をもって実感している今日この頃です。