MIS.W 公式ブログ

早稲田大学公認、情報系創作サークル「早稲田大学経営情報学会」(MIS.W)の公式ブログです!

GPUでプログラミング【新歓ブログリレー2019 11日目】

こんばんわ、52代のtakowasabiです。

みなさん、プログラムって動くの遅くないですか?

私は遅いと思います。なので早くします。

GPU

そこから?って感じでもありますがGPUについて軽く説明します。

GPUはパソコンでゲームをする人ならおなじみのグラフィックボードの上に搭載される計算機のことです。普段は膨大な処理能力を要する画像処理を行い、画面への描画をお手伝いしています。

しかし最近は、持ち前の高い計算能力を生かして、その活躍の場は広がっています。

その代表的なものが機械学習でしょう。(最近人工知能とかAIとか呼ばれるやつです)

細かな計算の塊である機械学習を、GPUを使えば小規模な施設で簡単に行うことが出来るということで、その需要はとどまるところを知りません。

そんな、今熱いGPUの中でも、最も一般的なメーカーの一つであるNVIDIAGPUを用いて、今回はプログラムの高速化を試みていきます。

f:id:tomioka2012:20190406010038j:plain

こんなロゴマークのメーカーです(ゲームのタイトル表示の前とかで見ることもあるのでは?)

CUDA

GPUなんて複雑そうなもの、アマチュアに動かせるの?と思ってる方に朗報です。

NVIDIAは、そんな悩める一般人のために誰でも無料で使えて簡単にGPUが動かせる環境を用意してくれています。

それがCUDAです。

どのくらい簡単かというと、C言語の関数の最初に__global__をつけるだけです。

__global__ void helloFromGPU()
{
    printf("Hello World from GPU!\n");
}

この関数(CUDAの用語ではカーネルと呼ばれる)を呼ぶことで、GPUに"Hello World"を言わせることが出来ます。

呼び出し側は以下のような感じになります。

int main(int argc, char **argv)
{
    helloFromGPU<<<1, 10>>>();
    cudaDeviceSynchronize();
    return 0;
}

<<<1, 10>>>という謎の部分とcudaDeviceSynchronize()という謎の関数を呼び出していますが、これで無事に10個の"Hello World"が出力されます。

ちなみに<<<1, 10>>>は起動するスレッドの数(1 x 10個)を表しており、cudaDeviceSynchronize()GPUの処理が終わるまで待つための関数です。

環境構築

環境構築はWindowsでも(運が良ければ)すごく簡単です。

Windowsで必要なのは「VisualStudio2017」(VS2019は対応してるか要確認)と「CUDA Toolkit」です。

クイックスタートガイド(英語)などをよく見てこちらからダウンロードできます。

VisualStudioの細かい更新で使えなくなっちゃうようなトラブルが(聞いた話では)多くあるらしいのでそこら辺はご注意ください。

Windowsでの導入はこちらがとても丁寧で心強かったです。

nvccとかnvidia-smiとかのコマンドを認識するようになれば環境構築完了です。

当たり判定

私はゲームが大好きです。ゲーム作りに使えそうな処理を高速化したいと思います。

そこで、ゲームで重くなりがちな処理の一つとして当たり判定を題材にしていきます。

当たり判定は奥が深い処理なので、今回は簡単に実装を行いました。

普通は四分木などを用いて空間分割などを行って処理を高速化するのですが、今回は総当たりで当たり判定をしています。(n個のオブジェクトに対してn(n-1)/2回の当たり判定を行う)

結果

まあ細かい理論とかはソースコードhttps://github.com/takowasaby/ShinkanBlog)とかを読んでもらうことにして、ここでは結果をご紹介します。

以下の環境で1000個の円で当たり判定&衝突の処理を行いました。(画面描画はOpenSiv3Dで行っています)

  • CPU:Intel(R) Core(TM) i7-8700 @ 3.20GHz
  • GPUGeForce GTX 1070
  • RAM:16.0GB
  • OS:Windows10
  • CUDA:CUDA Toolkit 10.0

まずはCPUでの結果がこちら

f:id:tomioka2012:20190406010022g:plain

かなりカクついていますね。処理が間に合わず、描画のfpsが低下しています。

次にGPUを使った結果がこちら

f:id:tomioka2012:20190406010036g:plain

ヌルヌル動いていますね。処理が早くなっている証拠です。

お互いの処理時間を比べると以下のような感じでした。

当たり判定&衝突処理の時間(ms) fps換算(fps)
CPU 383.95 2.60
GPU 16.14 61.95

かなり速くなってますね、GPUのちからってすげー!

まとめ

ここまで読んでいただいてありがとうございます。

WindowsでCUDAをいじったのは初めてだったので疲れました。(その分動いた時の感動はひとしおでした)

新歓ブログでこういったことを書くのにはちゃんとした理由があって、「MIS.Wのプログラミング研究会には、なんか変なことしてる人がいるんだなぁ」と思ってもらえればそれで充分かなと思っています。

MIS.Wでは、プログラミング研究会に関わらず、様々なジャンルに挑戦している人間ばかりが在籍しています。そんな人たちばかりの環境に入れば、あなたも何かを始めずにはいられないはずです!

明日のブログリレーは葵さんの「Webデザインのススメ」です。最近MIS.W内で勢力を増しているWebデザイン班の班長による布教記事ですね。これは見逃せない......

裏話

実は、上の結果はCPUの最適化を切った状態での比較です。(懺悔)

CPUの最適化を入れると、CPUでも5000個ぐらいの円での衝突判定がヌルヌル動いたので、正直驚きました。

今回のGPUでの実装は、CPUと同じコードを使っている部分が多く、その点でGPUのスペックをまだまだ生かしきれていません。

高速化は本来、動くようになってからが本番です。

使うメモリの領域を変えたり、スレッドの構成を変えたり、CUDAでは様々な最適化が行えるような機能が多く供えられています。それらをフル活用していくことが、最速プログラマーへの道です。

あなたも、私と一緒に最速プログラマーを目指しませんか?(きれいにまとめたつもり)

参考文献

『CUDA C プロフェッショナル プログラミング』(株式会社インプレス)