L.Entisの日記: レイトレのポリ数による速度比較 5
日記 by
L.Entis
というわけで、自家製レイトレコードに、ポリゴン数を変えたデータを突っ込んで、レンダリング時間がどのように推移するか実験しました。
結果を動画にまとめたものはこちら(ニコニコ動画)にアップしてあります。
グラフとかが見えるだけで、味気ない動画ですが。
ポリ数を増やす方法ですが、一つはオブジェクトを沢山配置する方法、もう一つはメッシュの分割数を上げる方法の2つをそれぞれテストしました。
これは、最適化アルゴリズムで特性に違いが出ることが予想されたためです。
何れも、以前にアップした動画で使用しているモデルをベースにしています。
(三角ポリゴンベースで、174 ポリゴン)
【結果】オブジェクトを並べた場合;
174x1 174x4 174x9 174x16 174x64
CPUx1 140 300 415 540 1180
CPUx4 32 72 100 130 289
GPU+CPUx1 186 296 397 475 954
GPU(Simple)+CPUx1 219 433 806 1331 5293
【結果】メッシュの密度を上げた場合;
174x1 744x1 1710x1 3072x1 3072x4
CPUx1 140 193 307 465 1091
CPUx4 32 47 76 112 259
GPU+CPUx1 186 191 245 301 798
GPU(Simple)+CPUx1 219 347 604 948 4310
数値はミリ秒で、数十回レンダリングしたレンダリング時間の平均を取っています。
表の上の行(174x1, 174x4, etc...)の数値はポリゴン数(三角ポリゴン)で、x4 とか x9 などと書いてあるのは、オブジェクトを4つとか9つ並べましたよ、という意味です。
メッシュ分割のほうの一番右側の列は、メッシュの分割をこれ以上するのが面倒だったので、とりあえず密度を上げたオブジェクトを並べて増やしたものになります。
おおよそ、CPUx1 と GPU が同じような性能になっているのが分かると思います。(GPUのほうがやや速い)
因みに、174x1 の列の CPUx1 と GPU の差(逆転している)は、今回のテストで行った条件での、GPU 側の処理結果を CPU に転送するのに要する時間に比較的近いです。(この差よりは小さいですが)
あと、面白い現象としては、CPUx1 と CPUx4 では、CPUx4 の方が CPUx1 より4倍以上速くなっているということでしょうか。
普通、4倍近く速くなる事はあっても、4倍以上になることは無いので不思議な現象ですが、メモリアクセスやキャッシュの関係で何かいいことがあったのかもしれません。
(CPUx4の測定値はかなり安定していたのに対して、CPUx1は少しぶれがあったので、その計測上の影響の可能性が無いわけではありませんが)
因みに、動画でも説明してありますが、GPU(Simple) は GPU 側の最適化アルゴリズムを取ったら(つまりGPUらしく(?)ゴリ押ししたら)どうなるか、という数値です。
なんか、「GPU は速い、爆速だ!にも関わらずあまりパフォーマンスが出ていないのはプログラムが悪い」というGPU信仰が多く見受けられるので、あえて計測しました。
(と言いつつ、これでも少し最適化のコードが残っているのですが、遅くするためにコードをいじくるのが嫌だったのでそのまま)
GPU 信者の人は少し冷静になって考えていただきたいのですが、仮に1光線と1ポリゴンの当たり判定に必要な演算量が 1 FLO(PS) だったとして、640x480 のピクセル数に対して、10000回ループしたら(1万ポリゴンに対して1回づつ当たり判定を行ったら)、その演算量は 640*480*10000 = 3072*10^6(約 3G FLO(PS))になります。
1 FLO(PS) では、一番手前でヒットしたポリゴンを探すための比較演算をやるだけで終わりです。
(後で1フレーム1秒の演算量と比較しているので、便宜的に演算回数=FLOPSということで話を進めます(PS が /sec の略なのでなんか変ですが一応括弧つきで……気分的には FLOp と書きたいところですが))
しかも、陰の判定のためにはそこから光源方向に光線追跡しなければなりませんし、反射や屈折のための光線追跡も必要です。(今回のテストオブジェクトはまさにそんなモデルです)
仮にピクセルあたり 3~4 回の光線追跡が必要だった場合、1ポリゴンとの当たり判定に必要な演算量が 1 FLO(PS) でも、10G FLO(PS) ほど必要と言うことになります。
ところで、1つのポリゴンは3つの頂点から成り、1つの頂点は3つの要素から成ります。
ポリゴンの当たり判定にはどの程度の演算量が必要でしょうか?
9つの値に対して 1 回づつ演算を行っただけでも 9 FLO(PS) です。2回なら 18 FLO(PS)。
もし 50 FLO(PS) を要してしまったら、それだけで GPU のピーク性能に到達するような勢いです。(1フレームを 1000ms でレンダリングできる、というのがここ)
他にメモリのアクセスもあるわけです。(むしろこちらのほうがずっと凶悪だろうと思いますが、GPU 信者の人にはピーク演算性能の話のほうが納得できるでしょう)
上の表を見てください。
一番右側の列は、1万ポリゴンを超えている領域です。
単純には語れませんが、ピーク演算性能と言う単純な指標だけでは語れないものがそこに存在しているのが分かると思います。
(少なくとも公称値ではCPUの方がGPUより一桁、演算性能が下のはずなのです)
結果を動画にまとめたものはこちら(ニコニコ動画)にアップしてあります。
グラフとかが見えるだけで、味気ない動画ですが。
ポリ数を増やす方法ですが、一つはオブジェクトを沢山配置する方法、もう一つはメッシュの分割数を上げる方法の2つをそれぞれテストしました。
これは、最適化アルゴリズムで特性に違いが出ることが予想されたためです。
何れも、以前にアップした動画で使用しているモデルをベースにしています。
(三角ポリゴンベースで、174 ポリゴン)
【結果】オブジェクトを並べた場合;
174x1 174x4 174x9 174x16 174x64
CPUx1 140 300 415 540 1180
CPUx4 32 72 100 130 289
GPU+CPUx1 186 296 397 475 954
GPU(Simple)+CPUx1 219 433 806 1331 5293
【結果】メッシュの密度を上げた場合;
174x1 744x1 1710x1 3072x1 3072x4
CPUx1 140 193 307 465 1091
CPUx4 32 47 76 112 259
GPU+CPUx1 186 191 245 301 798
GPU(Simple)+CPUx1 219 347 604 948 4310
数値はミリ秒で、数十回レンダリングしたレンダリング時間の平均を取っています。
表の上の行(174x1, 174x4, etc...)の数値はポリゴン数(三角ポリゴン)で、x4 とか x9 などと書いてあるのは、オブジェクトを4つとか9つ並べましたよ、という意味です。
メッシュ分割のほうの一番右側の列は、メッシュの分割をこれ以上するのが面倒だったので、とりあえず密度を上げたオブジェクトを並べて増やしたものになります。
おおよそ、CPUx1 と GPU が同じような性能になっているのが分かると思います。(GPUのほうがやや速い)
因みに、174x1 の列の CPUx1 と GPU の差(逆転している)は、今回のテストで行った条件での、GPU 側の処理結果を CPU に転送するのに要する時間に比較的近いです。(この差よりは小さいですが)
あと、面白い現象としては、CPUx1 と CPUx4 では、CPUx4 の方が CPUx1 より4倍以上速くなっているということでしょうか。
普通、4倍近く速くなる事はあっても、4倍以上になることは無いので不思議な現象ですが、メモリアクセスやキャッシュの関係で何かいいことがあったのかもしれません。
(CPUx4の測定値はかなり安定していたのに対して、CPUx1は少しぶれがあったので、その計測上の影響の可能性が無いわけではありませんが)
因みに、動画でも説明してありますが、GPU(Simple) は GPU 側の最適化アルゴリズムを取ったら(つまりGPUらしく(?)ゴリ押ししたら)どうなるか、という数値です。
なんか、「GPU は速い、爆速だ!にも関わらずあまりパフォーマンスが出ていないのはプログラムが悪い」というGPU信仰が多く見受けられるので、あえて計測しました。
(と言いつつ、これでも少し最適化のコードが残っているのですが、遅くするためにコードをいじくるのが嫌だったのでそのまま)
GPU 信者の人は少し冷静になって考えていただきたいのですが、仮に1光線と1ポリゴンの当たり判定に必要な演算量が 1 FLO(PS) だったとして、640x480 のピクセル数に対して、10000回ループしたら(1万ポリゴンに対して1回づつ当たり判定を行ったら)、その演算量は 640*480*10000 = 3072*10^6(約 3G FLO(PS))になります。
1 FLO(PS) では、一番手前でヒットしたポリゴンを探すための比較演算をやるだけで終わりです。
(後で1フレーム1秒の演算量と比較しているので、便宜的に演算回数=FLOPSということで話を進めます(PS が /sec の略なのでなんか変ですが一応括弧つきで……気分的には FLOp と書きたいところですが))
しかも、陰の判定のためにはそこから光源方向に光線追跡しなければなりませんし、反射や屈折のための光線追跡も必要です。(今回のテストオブジェクトはまさにそんなモデルです)
仮にピクセルあたり 3~4 回の光線追跡が必要だった場合、1ポリゴンとの当たり判定に必要な演算量が 1 FLO(PS) でも、10G FLO(PS) ほど必要と言うことになります。
ところで、1つのポリゴンは3つの頂点から成り、1つの頂点は3つの要素から成ります。
ポリゴンの当たり判定にはどの程度の演算量が必要でしょうか?
9つの値に対して 1 回づつ演算を行っただけでも 9 FLO(PS) です。2回なら 18 FLO(PS)。
もし 50 FLO(PS) を要してしまったら、それだけで GPU のピーク性能に到達するような勢いです。(1フレームを 1000ms でレンダリングできる、というのがここ)
他にメモリのアクセスもあるわけです。(むしろこちらのほうがずっと凶悪だろうと思いますが、GPU 信者の人にはピーク演算性能の話のほうが納得できるでしょう)
上の表を見てください。
一番右側の列は、1万ポリゴンを超えている領域です。
単純には語れませんが、ピーク演算性能と言う単純な指標だけでは語れないものがそこに存在しているのが分かると思います。
(少なくとも公称値ではCPUの方がGPUより一桁、演算性能が下のはずなのです)
言葉を忘れてしまった (スコア:2)
-- Takehiro TOMINAGA // may the source be with you!
GPUの使用効率 (スコア:1)
えっと、ニコ動から流れてきたのですが
GTX275(約1TFlops)とCore2Quad 2.66GHz(約50GFlops)で、ピーク性能が20倍ですね。1Core比だと80倍。
1CoreとGPUがほぼ同じってことは、CPU内での光線追跡と照度計算の時間比率次第ですが、
GPUはピークの1/100なオーダーのぐらいしか出せてないってことですね。
このぐらいの性能となると、おそらくメモリアクセスがかなりネックになってるんじゃないでしょうか。
所要時間の99%はメモリ読み込み待ちって感じで。
過去の日記エントリで8600GTS→GTX275で10倍高速ってありましたけど、
メモリバス速度は32GB/s→127GB/sで4倍。
SP数は32→240で7.5倍
ですね。
SP数が多いと、それだけローカルメモリに読み込んだデータの利用回数が上がるので、メモリアクセス軽減に役立ってる気がします。
ピーク性能の1%ってことは、コアの演算処理にかかる時間はほとんど無視できるレベルなわけで、
メモリ読み込みにかかる時間だけを見るとコア数7.5倍で、メモリ読み込み回数7.5分の1、メモリ速度4倍でメモリ読み込み時間4分の1で、あわせて30倍 GTX275が速いという机上の空論的理論値に。
ここから先の高速化は、いかにメモリアクセスを減らす/局所化することができるかどうかでしょう。
レイトレだと、2次レイ以降は必要なデータが分散していて局所化できないので、かなりGPUに不向きなアプリケーションだと思います。
ていうか、そのあたりのCUDAでうまく高速処理できるのかはなはだ疑問だったので、
GPUでレイトレと聞いて驚いたのでした。
Re:GPUの使用効率 (スコア:1)
メモリアクセスは悩ましいところです。
もうちょっと共有メモリが大きければまだやりようもありそうな気もするのですが、現状、複数のSPが同時アクセスしてくれるのを期待する程度しか出来てません。
メッシュの密度 (スコア:1)
Re:メッシュの密度 (スコア:1)
ただ、単純な逐一判定が必要になる局面になると、処理の面で GPU が有利になるのではないかと思います。