一旦停止では必ず白線の前で止まりましょう
こんにちわ、こんばんわ。かえるのクーです。
CUDAデバッガ(Nsight)がやっと止まってくれたので、CUDA入門を続けます。
あいかわらず2~3日かけて実際にすこしずつやりながら、書いていきます。
ボクにはめずらしく、トレース可能なチュートリアルにします。(おたまじゃくしさんや小中学生のみなさんでもきっとできるtutorialにしてみます)
まずは、CUDAプロジェクトを起動してサンプルを動作させてみます。
VisualStudio 2017 の起動とプロジェクト作成
1. 起動して、「新しいプロジェクトの作成」をします。
2. NVIDIAのなかの 「CUDA 10.0」 を選択します。
3. 「CUDA 10.0 Runtime」 を選択します。
4. 名前を入れます。プログラムの名前とソリューションの名前になります。
5. 「OK」を押すとプロジェクトが作成され、ひな形のプログラムが準備されます。
6. 入力した名前のソリューション (例では myFirstCUDA.sln)とkernel.cu ファイル(ソースプログラムサンプル)が準備され、表示されます。
7. ビルドメニューの「ソリューションのビルド」を行い、プログラムの作成を行います。デフォルトでは「デバッグモード」でビルドされます。
8. 出力欄(出力ペイン)にビルド結果が表示されます。コード系の警告が表示されますが、今は気にしないでOKです。
プロジェクトのフォルダの下にx64\Debug の下にmyFirstCUDA.exe ができあがります。(ほかにもリンク用やデバッグ用のファイルができます)
9. デバッグメニューから「デバッグなしで開始」を選択してプログラムを実行します。
10. コンソールウインドウが別に起動し、処理結果が表示されます。
ここまでで、デバッグの練習に使用するプログラムが実際に動くことが確認できました。
サンプルプログラムの説明
5つの要素の配列 a と配列 b を足して、配列 c に代入します。
プログラムはおおまかに
1~7行目までのヘッダファイルを取り込みとプロトタイプ宣言
9~13行目までのGPUで実行するカーネル計算部分(計算のかなめ)
15~41行目までのメイン部分
44~121行目までのサブ部分 に分かれています。
べたべたに実行順に簡単に説明します。
[0] C(C++)は main()と書いた部分から実行が開始されます。
[1] CPU(ホスト)側に計算のもととなる配列 a, b と計算結果を格納する c を準備します。
[2] CUDA計算の前後処理を含めてをまとめたaddWithCudaを実行します。
[3] GPUの0番を使うことを指定します。(1台のPCに複数のGPUを組み込めます)
[4] 配列 c の場所をGPU(デバイス)側に準備します。
[5] 配列 a の場所をGPU(デバイス)側に準備します。
[6] 配列 b の場所をGPU(デバイス)側へ準備します。
[7] 配列 a をCPU(ホスト)側からGPU(デバイス)側へ複写します。
[8] 配列 b をCPU(ホスト)側からGPU(デバイス)側へ複写します。
[9] 9行目から13行目までの「カーネル」の計算を実行します。この部分がマルチスレッドで起動し、GPUでは並列で同時に計算します。
[10] スレッドのインデックスを取得し「自分」がどの計算をすればよいのか知ります。
[11] 指定された計算を並列で行います。a と bの値を加算し、c に格納します。
[12] エラーがあれば、その状態を取得できます。
[13] デバイスの動機をとって、計算を完了します。
[14] 計算結果をデバイス(GPU)側からホスト(CPU)側に複写します。
[15]~[17] [4]~[6]で準備した計算作業用のエリアを開放します。
[18] 計算結果を表示します。
[19] GPUをリセットして次の計算に備えます。
[20] プログラムが終了するとCPU側の使用メモリが解放されます。
ポイント
カーネル計算はデバイス(GPU)で並列に行われます。
計算の前処理、後処理でデータの準備、複写や計算後の後始末を記載します。
カーネル計算部以外はホスト(CPU)から制御(またはGPUへ依頼)されます。
Nsightデバッガを動作させるための準備
Nsightは以下の2つの部分で構成されています。
「Nsight Monitor」GPUのデバッグを制御・モニタする
「Nsight for Visual Studio」ソースやブレークポイント、実行、確認オペレーションをコントロールします。
それぞれに設定が必要です。(例題であれば、環境にもよりますが、何も設定変更せずに動くかもしれません)
Nsight Monitorの設定
[1] Nsight Monitor を管理者として起動します。
[2] 画面右下部から常駐プログラムを表示し、「Nsight Monitor」アイコンから Optionsを選択します。
[3] Generalの「WDDM TDR Delay」を 30~40(秒)に設定します。
[4] 「WDDM TDR Enabled」を False に設定します。
設定したらいモニタを一旦Exitしておきます。
Nsight for Visual Studioの設定
[5] Visual Studioの右側にあるソリューションエクスプローラから、ソリューション名の上で右ボタンでメニューを表示し、「プロパティ」を選択します。
構成プロパティのCUDA C/C++ のDeviceの値を設定します。
[6] Code Genaration をお持ちのGPU の世代に設定します。例えば、GTX 1060の場合は 、compute_61, sm_61です。複数続けて書くこともできます。
(例) compute_35, sm_35; compute_61, sm_61 など。
デバイス毎の値はここを参照ください。
[7] Genarate GPU Debug Information がはい (-G)になっていることを確認します。(もとからこれに設定されていますが、いろいろ触っていると、誤っていいえにしていないか、などを確認します)
[8] はい。(-lineinfo) デバッグ時に行番号情報を出します。(いいえのままでもデバッグはできます)
さて、準備は整いました。いよいよデバッグです!
とまれでは必ず一旦停止!
デバッグします。あっけないくらいに簡単です。
<1> カーネル側のソース行を選択してブレークポインタを設定します。
ブレークポインタの削除
<2> ブレークポイントの削除も必要に応じて行います。
<3> Nsightメニューから Start CUDA Debugging (Next-Gen)を選択します。
main() の先頭で止まります。通常とおりGPU側のデバッグが可能です。
<4> メニュの下へもぐる矢印が「ステップイン」(F11)です。
飛び越える矢印が「ステップオーバー」(F10)です。
上へ浮かび上がる矢印が「ステップアウト」(Shift + F11)です。
変数の内容をすぐに小窓で確認できます。
<5> 変数を選択し、変数の内容を確認できます。そのまま画面に張り付けておくこともできます。この張り付けは記憶でき、ソリューションの保存で記録されます。
従来からのクイックウオッチでも確認できます。
ここがこの記事の要です。実はこの記事はこの画面だけでよかったかもしれません。
すでに読んでもらえない長さになっています。
<6>NsightのWindowsメニューから各種の情報表示が起動できます。(GPU関連の情報窓の新規表示はデバッグ中にしか表示されません)
Nsightのバージョンによっては操作方法(スレッドをどのように選ぶか)が違います。
<7>Worp(ワープ/ウォープ)はスレッドのまとまりごとに表示されます。サンプルは小さいので1ワープのみ表示されています。
<8>Lenes(レーン)はスレッドの単位です。サンプルでは5スレッド動作します。
<9>Registers(GPU内の計算状態が表示されます)
あ、9番がダブってしまいました。
<9>ワープ(Warp)の中のスレッド表示欄、またはレーン(Lean)のスレッドの選択欄で
特定のスレッドを選択して確認ができます。
<10>選択したスレッド(コア)の計算内容を確認できます。
F10で1ステップずつ実行でき、スレッドを切り替えながら、内容を確認できるので、初心者にはとても助かります。
まだ書きたいことがあるのですが、サイトの編集エディタの限界(止まったように編集が遅い)
なので、以上でNSightでのデバッグ入門はいったん終了です。
雪の時期がもうそこまで
次回は:雪が降らなければ(冬眠にはいらなければ)、サンプルプログラムをすこし変更してデバッグしてみます。(後記:寒波がきたのでこの企画は中止となりました)
(追記)この記事の誤字脱字は助手が修正しました。