1. はじめに
SfMをかじりはじめてから、Regard3DとBundlerを試してみた。実際にいろいろ撮影して3Dモデルを作成しようとするが、マッチングしないケースやマッチングしてもその後の画像の復元が不十分など、なかなかうまくいかないケースも多い。改めて、最初に読んだ SfMのソフトの比較記事 を読む COLMAPというソフトがよさそうである。別の記事 でもCOLMAPの結果が最もきれいであるとしていた。
そこで、COLMAPを試すことにした。マッチングはやはりできたりできなかったりだったが、マッチングできた場合でもその後のdensificationではcuda errorで落ちてしまう。ネットの 記事 によると、densificationにはcudaを走らせるGPUが必要とあった。
「cudaって何?」
ネットで調べると、cudaはnVIDIA社のGPUを並列処理プロセッサとして利用するためのプログラミング環境 のようだ(例えば、https://co-crea.jp/wp-content/uploads/2016/07/File_2.pdf による)。ここで、かつてnVIDIA社のGPUであるQuadro K600を別の目的で自分のPCに増設したことを思い出した。その目的のためには、全く使用せず宝の持ち腐れになっていた。
「cudaをインストールして、COLMAPでdensificaionができるようにしてみよう。」
というわけでcudaを触ってみることにした。この記事はその時の試行錯誤のメモです。
2. cudaのインストール:失敗編
ネットに良い記事(https://www.kkaneko.jp/tools/win/cuda.html、以下[K]とする)があったので、それを踏襲してインストールを試みる。おおよその順序は以下のとおり。
(1)Visual Studioのインストール
(2)NVIDIAドライバーのインストール
(3)NVIDIAツールキットのインストール
(4)NVIDIA cuDNNのインストール
(5)nvccの実行
(6)NVIDIA cudaサンプルプログラムのビルドと実行
2-1 Visual Studioのインストール
[K]にしたがって Visual Studio Community 2022 をインストールする。時間はかかるが問題なくインストールが行えた。
2-2 NVIDIAドライバーのインストール
NVIDIAドライバダウンロードのページにいき製品に適したドライバーを特定し、ダウンロード、インストールした。PCに搭載されているGPUは Quadro K600 だったので
製品のタイプ:NVIDIA RTX / Quadro
製品シリーズ:Quadro Series
製品ファミリー:Quadro K600
オペレーティングシステム:Windows 10 64-bit
とした。
2-3 NVIDIAツールキットのインストール
実施時点(2022年5月)で最新のversion11.6.2をダウンロードし、インストールする。これも無事に終了。その後、環境変数 PATH, CUDA_PATH, CUDA_PATH_V11_6 が正しく設定されていることを確認。
2-4 NVIDIA cuDNNのインストール
これが必要かどうか分からなかったが、[K]にあるとおりにダウンロードしインストール。
2-5 nvccの実行
nvccは、"NVIDIA CUDA Compiler"の略でC/C++言語をもとに独自の拡張を行った専用言語のコンパイラらしい。
[K]にあるとおり、https://developer.nvidia.com/blog/easy-introduction-cuda-c-and-c/ にあるコードをテキストエディタで編集しhello.cuとして保存した。nvccでのsourceファイルは、cuという拡張子とするらしい。
Vusual Studioをインストールすると一緒にインストールされる x64 Native Tools コマンドプロンプト で、nvccによりビルドし、作成されたexeファイルを実行する。そうすると、 「Max error: 2.000000」と表示された。[K]によると、「Max error: 0.000000」と表示されるとOKとのことであったが、大した違いでないと考え先に進んだ。結果的にはこれが大きな間違いだった。
2-6 NVIDIA cudaサンプルプログラムのビルドと実行
cuda をインストールすると C:\ProgramData\NVIDIA Corporation\CUDA Samples\v11.6\cuda-samples にcudaのサンプルプログラムが大量に保存される。このフォルダにvusual studio 2022のソリューションファイル Samples_VS2022.sln があるので、これをダブルクリックして立ち上げる。[K]にしたがい、「ソリューションの再ターゲット」、「ソリューションのビルド」を実行。サンプルプログラムが186あるので、ビルドには相当時間がかかった。出てきた結果は、警告の山と19個のエラー。
186のサンプルプログラムのうち、exeファイルができているものが相当数ある。そのうちの一つがnbody。多体問題のシミュレーションのようだ。そこで改めてnbody単独でビルドすると問題なくビルドできたので、exeを実行してみる。すると、次のメッセージが出た。
CUDA error at C:\ProgramData\NVIDIA Corporation\CUDA Samples\v11.6\cuda- samples\Samples\5_Domain_Specific\nbody\bodysystemcuda_impl.h:302 code=13(cudaErrorInvalidSymbol) "setSofteningSquared(softeningSq)"
そこでcode13に関する情報をネットで調べると、https://www.knime.com/deeplearning4j に以下の記載があった。
どうもGPUである Quadro K600 と cuda のバージョン(ここでは11.6)が合わないらしい。そこで、https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ をみると、NVIDIAのGPUのアーキテクチャと対応するcudaのバージョンの記載があった。Qudro K600のアーキテクチャはなんだろうと思い、近くにあったケースをみると「NVIDIA Kepler アーキテクチャにより、・・・」と書いてあった。上のサイトには、Keplerはcuda5からcuda10まで対応と書いてある。それじゃ、cuda10をインストールしてみるか。
3. cudaのインストール:成功(したと思われる)編
cuda10についても[K]と同じ方によるインストールのガイダンス
(https://www.kkaneko.jp/tools/win/cuda10.html、以下[K2]とする)があった。これにしたがいインストールを行うことにした。
手始めにvisual studio 2022を削除して、2017をインストールする。これは、cuda10が対応するvisual studioのバージョンは2017までであることによる。後は基本的にcuda11のときと同じでインストールは順調に進んだ。
「2-5 nvccの実行」にあげたサンプルを実行すると、めでたく「Max error: 0.000000」と表示された。
そこで最終段階のサンプルプログラムのビルドを行った。cuda10では、サンプルプログラムの数が174に減っている。今回は、174のうち4つのサンプルのビルドに失敗したが、エラーはでなかった。
そこで、いくつかのサンプルを実施してみた。うまくいくものと、いかないものがあった。下はoceanFFTの実施時のキャプチャ画面、実際はダイナミックな動きに迫力がある。とにかく、サンプルプログラムがいくつも動いたので良しとしよう。
4. cudaのコーディング
サンプルプログラムが動くだけでは、あまりよくわかった気にならないので、実際のコーディングがどうなっているのか知りたくなった。丁度 良い資料 があったので、これにそってコーディングのマネゴトをしてみた。単純に行列の掛け算を行うというプログラムである。必要なコードは全て書いてあったので、visual studio 2017で単に編集しただけである。
CPUだけ使ったcのプログラムとcudaでのプログラムの2種類のコードが示されているので計算速度の差が実感できるようになっている。
・通常のCでのコーディング
visual studioを立ち上げ、新規プロジェクト(ここではConsoleApplication1とした)でコンソールを選びコードを書くだけ。ビルドすれば、Debugフォルダーに.exeファイルができる。これをコマンドプロンプトから実行できる。
C:\Users\ユーザー名\source\repos\ConsoleApplication1 に.slnファイルができるので、コードを直したければこれを開けばよい。
・cudaでのコーディング
visual studioを立ち上げてから、ファイル>新規作成>プロジェクト でプロジェクトを作成する。このとき現れるウィンドウの左側に並んだ「インストール済み」の中から、NVIDIAを選ぶ。すると kernel.cu ができるので、必要なら後で適当に名前を変える。
__global__ 関数がcudaプログラムの要のようで、これはmain関数の前におかなければならない。Cの場合、mainで呼び出す関数はその前に定義されていなければならないようだ。Cについてはほとんど何も知らないのでかなりいい加減。
2つのプログラムを比較すると、明らかにcudaを利用したプログラムの計算速度の方が早かった。参考にした資料には、計算時間が表示されていたが、そのコードが示されていなかったので、計算速度を体感しただけである。
一応、cudaが動くようになったので、次は、COLMAPのdesificationがうまくいくかどうかやってみよう。