Posted at

GPGPUに手を出す前に検討すべき事について

More than 5 years have passed since last update.

この記事はGPGPU Advent Calendarの16日目です。


さて、1回だけ書くという話だったのに、人が集まらなくて2回目を書かないといけなくなったので、無理矢理ネタを考えてみた。

自分の3回目はこのまま行くと最終日だが、山田が凄いのを代わりに書いてくれるらしいので、今回が最後だ。


今回はGPGPUに手を出す前に検討すべき事について。

GPUGPUに興味があって触ってみたい人や、GPGPUを研究のテーマにする人などはすぐにGPGPUに手を出すべきだ。

興味が伴うプログラミングは大きな学習成果を伴うだろう。

ただし、そうではなく業務上などで今あるプログラムを速く動かす必要がある人は、GPGPUに手を出す前に次のような事を検討すべきである。

まずは、プログラムを実行するワークフローを変えられないかどうか。

例えば、夜間にバッチ処理として実行して翌日に結果が取れれば良いなら、わざわざ高速化する必要は無いだろう。

まあ、高速化することで今までと違う使い方が出来るようになって、イノベーションが生まれることもあるので、高速化しないというのは正しくない場合も多いのだけど。

次にハードウェアを交換することで、必要十分な速度にならないかの検討。

CPUを交換したりメモリの量を増やしたり、データをSSDにおいてみたりだ。

ハードウェアの交換で必要な速度が達成できるなら、さっさとそうするべきだろう。

ハードウェアの交換で必要な速度が達成できるか自分では分からない場合。

プログラムのボトルネックが計算か、I/Oか、ネットワークかが判断できないなら、

高速化の得意なソフトハウスへの発注というのも手だろう。(ステマ)

GPGPUが始まる前から高速化を得意としているソフトハウスなら、GPUを利用した高速化に限らず、最適な実現方法を提案してくれるはずだ。(さらにステマ)

ここまでは、自分でプログラムに手を入れない方法だったが、次からは自分の手を動かす方法。

コンパイラオプションやコンパイラ自体を見直すというのも手だ。

コンパイラの最適化オプションが設定されていないなら、設定するだけでもかなりの性能向上があるはずだ。

オプションを変更するだけで、必要な性能が達成できるなら手間は殆ど無い。

もし高速化したい処理が、一般的な処理であるならば、既に高速化されたミドルウェアを利用するのも手だ。

処理によっては無償のものから有償のものまで、いろいろと有るかもしれない。

速度を売りにしているミドルウェアなら、同じ処理を普通のプログラマが書いて、速度で勝つのはなかなか難しいだろう。(少しだけステマ)

プログラムを全て見直すことになるが、使用言語を見直すことも必要かもしれない。

速度がクリティカルな処理にインタプリタな言語を使っているなら、C言語などの実行バイナリが生成される言語で書き直す事で、十分に速くなるかもしれない。

まあ、ぶっちゃけ後から言語変えるとかお勧めしないので、速度が必要なら初めから、ちゃんと言語を選ぼう。

OpenMPをサポートしている言語なら、OpenMPのディレクティブをループの頭に1行追加するだけで、十分速くなるかもしれない。

ループの中の処理の内容によっては、そんな単純な話では無いかもしれないが、

OpenMPでの高速化が難しい処理はGPGPUで高速化するもの、おそらく大変だろう。

依存関係の無い、同時に実行可能な、そこそこの規模のタスクが幾つか存在するなら、

マルチスレッド化というのも手だ。

依存関係があるタスクのマルチスレッド化は排他制御とかいろいろと考えないといけないが、依存関係がないなら、割と簡単に実現出来るだろう。

プログラムの重い部分はループになっている事が多い。

元々のループ内の処理の規模によるが、ループアンロールをしてやるだけで、そこそこ速くなることもある。

あるいは、ループの中で毎回行っている計算を、可能ならループ外に追い出すなど、

いろいろな高速化のテクニックを試して見るのも良いだろう。

さてループの中を眺めて、お互いの処理に依存関係がなく並列性が十分に高く(個人的には数千以上を推奨)メモリアクセスがランダムではなく、GPGPUに向いている処理だと判断できたらいよいよGPGPUへ手を出そう。

ただ、処理に必要なデータや処理の結果生成されるデータの量が多く、データの転送の時間が元の処理よりも長いなら、残念だが諦めよう。

(データ転送の時間を隠蔽するテクニックとかを試して見る価値はある)

サンプルプログラムで転送速度を測っておけば、後は計算でおおよその転送に掛かるおおよその時間は求められるので、GPGPUに手を出す前に求めておくのも良いだろう。

ところで、高速化したい処理がGPGPUに向いていなかったらどうするか。

クラスタが利用出来るなら、MPIによる高速化も良いかもしれない。

しかし初めからMPIを前提にしていないプログラムを、後からMPIを利用するように修正するのはそこそこ大変だろう。

GPGPUに手を出せるほどのスキルがあるなら、SSEやAVXといったSIMD命令を使った

高速化も検討してみると良いかもしれない。

SSEも便利な命令が増えて、だいぶプログラムが組みやすくなっている。

SSEやAVXでの高速化を行うなら、ここからダウンロードできるIntel Intrinsics Guideは絶対に利用すべきだ。

さて、OpenMPやSIMD命令を使っても、まだ速度が足りない場合、2013年1月28日から購入可能な、Xeon Phiの購入するのも良いかもしれない。

512bitのSIMD命令を持つXeon Phiに載せることで、きっと性能は大きく上がるだろう。

ただしXeon PhiではSSEやAVX命令は動かないので、苦労してSSEやAVXを使った最適化をしているなら、元に戻すか512bitのSIMD命令に置き換えるのを忘れないように。

IntelによるとXeon Phiへのプログラムの移植は殆ど手間が掛からないらしい。(本当だろうか?)

というわけで、Xeon Phiはいろいろと楽しみである。

あっ・・GPGPU面白いですよ(汗)


上の記事中の検討の順番は適当でいいと思います。

意見が違っても許してやって下さい。

明らかに技術的に間違っている部分は修正するのでご連絡下さい。