CUDA
NVIDIA
C言語

CUDA Cで苦労しないための記録、GPUは複数枚買う&プログラミングのしやすさを求める

最初に

CUDA C をネットの情報をたよりに独学でやってみました。
成果としては・・
https://qiita.com/mokoenator/items/c9f4c4fd926b5b62db2a
のようなことができるようになったくらいです。
単語など、CUDA初めての人はわからないと思いますが、困ったときに思い出してみてください。

GPUは複数枚買う

CUDA Cをやるやらないに関わらず複数枚買っておきましょう。
PC1台に1枚は時間がかかりすぎます。実行して30分後に終わるとか、一晩寝て・・とかざらにあるんです。結局・・・・シミュレーション、機械学習、パスワード解析とかの長い時間かかる問題を扱う仕事なので、早いGPU&複数台の方がトライアンドエラー回数が稼げるので複数台GPUがあるといい。

1PCに複数台搭載するのはオススメしない。
1PCに1GPUがオススメ。
マルチGPU構成は最初から考慮しない。

複数台のGPUとPCを並べてAマシン、Bマシン、Cマシンでコード変えて実行して・・・
並列にするとパラメータ調整の回数が稼げるし、バグも早く見つけられる。
なので最初から複数台で作業したほうがいい。
(私は1070Tiを3枚もってます)
台数が増えれば増えるほど開発が早くなると思います。

GTX1080とtesla m40のベンチ比較だとあんまり差がないように感じるので1080を複数枚買った方が幸せ??

AWSでいいじゃないですか?って思うのですが、請求額が怖い。

なんども書きますが、1枚だと時間がかかりすぎる。学習意欲もおちる。

PCの構成は??

PCケースはいらない
ケースは飾り。(コレが書きたかった)
ゴム板にマザボ直置きで。

CPUは普通のオフィスワークができる程度で。
(GPUを効率的に使うのが目標なので)

メモリは8Gで十分。

Windowsなら
Visual Studio Professionalが動けばいい。
たしかProfessionalかCommunity じゃないとNsight が動かない。
これにはまって苦労した。

C言語は当たり前に使えるように

C言語は普通に使えないと話にならない。
C++は使えないと細かいことやるのに苦しい。

C#使えると楽しい。
C#からDLL経由でC++でCUDA C
みたいに使えるので楽しい

なんだかんだでPythonから使った方がらくでしょ?

Pythonから1050Tiを使うと正直CPUと変わんないです。
CUDA Cで頑張った方が早いです。
無駄にPythonでやらないで最初からCUDA Cをやりましょう。
(私の技術不足かもしれませんが)

ヘテロジニアスコンピューティング

知らない人は先にしらべるか、とにかくCUDAで腑に落ちるまで頑張って理解した方がいいです。なぜなら、GPUで扱える問題かどうか考えられないから。

情報はどこから・・

英語のサイトとCUDAのサンプルを読みまくる。
英語でわからないけど・・・
めんどくさがらずに読む。
日本語の情報は少ない。

CPUでも動くようにコードを書くとすごい楽

CUDA CはGPU上で動くコードを書くので、CPU上では動かないです。
でもCPUで動く関数を書くことができます。
なのでカーネルと共通して使えるよにする。
そうすると、CPUでテストしてGPUで動かして・・・ってできます。
そのときに便利なのが __device____host__を同時に使用するとCPUコードでもGPUコードでも両方利用できる。
もちろんすべて同時使用ってわけにはいかない・・・
CUDAにはCUDA用のライブラリしかあつかえません(CPU用のライブラリは使えない)。

GPUでしか動かないコードを書くことも必ずありますが、
コピーしてCPUでも動くようにしておきます。
CPUコードを作る&修正>GPUコードに手で変換する。
そうしておくとデバッグとかバグの原因追求が楽です。
(所詮GPUは計算しかできませんから・・・)

とにかくできるだけCPUとGPU両方で動くように書いく。

エラーのマクロは真面目に書いた方がいい。

本当に真面目に書いた方がいいです。そしてちゃんとマクロを使う。
わすれて大変な目にあうまえにマクロ。

カーネルの長時間実行エラー。

Windowsでは数秒でタイムアウトさせるようになっている。画面出力してなければ何も問題ないように思えるけどWindowsはそうじゃないらしい。「CUDAカーネル実行のタイムアウト」とかでしらべて実行時間を伸ばして対応しておいた方がいい。対応する前に一度位経験しとくと「これかぁ〜〜」と・・・あとでトラブルとして現れても対処できる。Teslaは映像出力系のトラブルはないらしい(出力機能がないからディスプレイとして認識されないのかも)

ちなみにエラーコードからは判断できなくて、2日潰すとか当たり前にありました。

最初からユニファイドメモリで組んだ方がわかりやすい

バグと戦う時間よりもユニファイドメモリを使った方が苦しくないです。
普通のメモリ管理の方がすこし早くて容量も少ない・・・らしい。
メモリ転送主体の処理ではないので・・・遅くなった感覚はしなかった。

大量のスレッドを立ちあげる感覚を早く身につける

・大量の仕事があるということ

・大量の処理前情報があるということ

・大量の処理結果があるということ
つまり
GPUメモリにある程度構造化した大量のデータを転送する必要があり
GPUメモリに結果があるので、ポインタのポインタ〜とかで送信、受信するかんじになる。
ってことを理解した方がいい。
(ユニファイドメモリじゃない普通の方式だとこの変数ポインタどっち??ってなる)

取り扱いたいデータを取り扱いたい形式でGPUに転送して、GPUからどーーんと起動する

制御文は書かない

制御文はCUDAコアで同期をとるため遅くなってしまう。
だから・・
if文はかかない。ifの除法で乗り切る。
for文はかかない。forの除法で乗り切るか・・・カーネル立ち上げてforの数だけ並列実行する。
直列するfor文を書かない。つまり前ループ値を引きずって処理するアルゴリズムで考えない
並列処理可能なように考え方を変えられないか検討する
そしたらカーネル立ち上げて並列処理できる。
でも・・・書かなきゃどうしようもないこともタクサンあるよね・・・

アセンブラ、マシン語

読めた方がいい。といってもそんなに読める必要はない。
アセンブラってこんなことできるんだよね?くらいで十分な気がする。
(自分がやってる分野が幼いからかな)
IF書いて>アセンブラかくにん>あれ?マシン語命令増えてんじゃん!
くらいがわかればOK
レジスタに読み込む消費サイクル数とか意識できるとよい。

プログラミングスキルよりも数学的な脳みそが必要

(わたしには)どうしようもないので・・・・あきらめる。