CUDA buildのGenerateDepsがとても遅い時のメモ

CUDAのビルドは、普通のC++コンパイルと比べるととても重いのだが、ある時からCUDAのビルドに入る前の処理が重い、という事態になって、とても困っていた。

この度めでたく解消したのでメモ書き。


CUDAのビルドに入る前段階が遅いというこの現象、Visual Studio 2015 + CUDA 8.0, Visual Studio 2015 + CUDA 10.1, Visual Studio 2019 + CUDA 10.1のいずれの環境でも発生していた。まあ、ビルドが遅いというとディスクの問題が考えられるけど、さすがにNVMe SSDでディスクが原因ということはないと思っていた(もしそうなら突然遅くなったりしない)。

そもそも、この現象はそれなりに報告例がある。
Slow compilation C++/Cuda GenerateDeps
Slow performance after update KB4093112
Why CUDA 7.5 + Visual Studio 2013 extremely slow “generating dependencies”?

問題はいずれの報告例も未解決だったり解決方法が「Windowsの再インストール」だったりで、ちょっとそれは…という感じだった。

解決の糸口になったのはこの記事。
Tremendously slow build with Visual Studio 2013 (MSBuild)
I had to edit Nvda.Build.CudaTasks.*.dll files because cl.exe /E (Preprocess to stdout) option in the dll file makes my build crawl. It happens during AddCudaCompileDeps target. Does anyone have similar experience?

この記事だけだとあまりよくわからないが、これで検索キーワードを少し変えると、
Visual Studio 2012 build hangs
I had to replace cl.exe /E option to /P within Nvda.Build.CudaTasks.vX.Y.dll files to evade the problem. There wasn't the problem few days ago so I'm not sure at all why the problem has surfaced.

そしてついにこちらの記事に行き着いて、対策方法を見つけることができた。

これによれば、Nvda.Build.CudaTasks.v*.*.dllの"/E"→"/P"に置換すればよいとのこと。(理由はよくわからないけど…)

CUDA 10.1なら、Nvda.Build.CudaTasks.v10.1.dllを、xeditなどのバイナリエディタで(wcharなので) "2F 00 45 00" (/E) を "2F 00 50 00"(/P)に置換すればよい。

NVEnc.slnのフルビルドの時間を測ってみたところ、GenerateDepsのところが200.7秒から8.7秒に大幅に高速化されているのがわかる。…というかこのぐらいが普通なのでは…?

実行コマンド
Msbuild NVEnc.sln /p:Configuration=RelStatic;Platform=x64 /t:Build /v:diag

変更前

タスク パフォーマンスの概要:
0 ミリ秒 Message 33 回呼び出し
0 ミリ秒 AssignTargetPath 9 回呼び出し
0 ミリ秒 AssignProjectConfiguration 5 回呼び出し
0 ミリ秒 CudaSetEnvironmentVariable 16 回呼び出し
0 ミリ秒 CountItems 15 回呼び出し
0 ミリ秒 ReadLinesFromFile 5 回呼び出し
0 ミリ秒 ResolvePaths 15 回呼び出し
0 ミリ秒 Touch 10 回呼び出し
0 ミリ秒 AssignCulture 1 回呼び出し
0 ミリ秒 CreateItem 1 回呼び出し
0 ミリ秒 SanitizePaths 31 回呼び出し
16 ミリ秒 SetEnv 100 回呼び出し
16 ミリ秒 SplitToItemMetadata 16 回呼び出し
16 ミリ秒 ResolvePackageFileConflicts 5 回呼び出し
16 ミリ秒 MakeDir 60 回呼び出し
16 ミリ秒 GetOutOfDateItems 6 回呼び出し
31 ミリ秒 XmlPeek 15 回呼び出し
31 ミリ秒 Delete 24 回呼び出し
94 ミリ秒 CustomBuild 1 回呼び出し
94 ミリ秒 ReadMetadataLinesFromItems 15 回呼び出し
172 ミリ秒 RC 1 回呼び出し
203 ミリ秒 WriteLinesToFile 38 回呼び出し
922 ミリ秒 Exec 2 回呼び出し
2265 ミリ秒 LIB 4 回呼び出し
6873 ミリ秒 CL 6 回呼び出し
35601 ミリ秒 Link 1 回呼び出し
143716 ミリ秒 CudaCompile 15 回呼び出し
200708 ミリ秒 GenerateDeps 15 回呼び出し
578494 ミリ秒 MSBuild 14 回呼び出し


変更後

タスク パフォーマンスの概要:
0 ミリ秒 AssignTargetPath 9 回呼び出し
0 ミリ秒 Delete 24 回呼び出し
0 ミリ秒 AssignProjectConfiguration 5 回呼び出し
0 ミリ秒 MakeDir 60 回呼び出し
0 ミリ秒 CudaSetEnvironmentVariable 16 回呼び出し
0 ミリ秒 ReadLinesFromFile 5 回呼び出し
0 ミリ秒 CountItems 15 回呼び出し
0 ミリ秒 XmlPeek 15 回呼び出し
0 ミリ秒 CreateItem 1 回呼び出し
0 ミリ秒 ResolvePaths 15 回呼び出し
0 ミリ秒 SanitizePaths 31 回呼び出し
0 ミリ秒 AssignCulture 1 回呼び出し
16 ミリ秒 Touch 10 回呼び出し
16 ミリ秒 GetOutOfDateItems 6 回呼び出し
16 ミリ秒 SplitToItemMetadata 16 回呼び出し
16 ミリ秒 Message 33 回呼び出し
16 ミリ秒 ResolvePackageFileConflicts 5 回呼び出し
31 ミリ秒 SetEnv 100 回呼び出し
109 ミリ秒 ReadMetadataLinesFromItems 15 回呼び出し
125 ミリ秒 CustomBuild 1 回呼び出し
125 ミリ秒 WriteLinesToFile 38 回呼び出し
156 ミリ秒 RC 1 回呼び出し
937 ミリ秒 Exec 2 回呼び出し
2234 ミリ秒 LIB 4 回呼び出し
6842 ミリ秒 CL 6 回呼び出し
8673 ミリ秒 GenerateDeps 15 回呼び出し
35755 ミリ秒 Link 1 回呼び出し
145903 ミリ秒 CudaCompile 15 回呼び出し
390885 ミリ秒 MSBuild 14 回呼び出し


というわけでだいぶ速くなったけど、CudaCompileはまだ遅い…。まあ、工程が複雑なうえにプロセスを起動したり落としたりを繰り返しているから仕方ないのかな?

あと、今回は工程ごとの時間を/v:diagを使って表示したかったのでMsbuildでビルドしたけど、Msbuildでビルドすると逐次実行になっているようで、普通にVisual StudioからビルドするとCudaCompileは並列実行されるので、そこまで苦痛ではない。GenerateDepsはVisual Studioからビルドしても並列にはならないようなので、結構苦痛だった。

Nvda.Build.CudaTasks.v10.1.dllのありか
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\extras\visual_studio_integration\MSBuildExtensions
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\BuildCustomizations
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\BuildCustomizations
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\BuildCustomizations

なんかいろんなとこにコピーされててどれが使われてるのかよくわからない。
スポンサーサイト



コメントの投稿

非公開コメント

余談 (MSBuildでビルド~)

CUDA自体には全く関係ない話になるかと思われますが、
> Msbuildでビルドすると逐次実行になっているようで、普通にVisual Studioからビルドすると~
MBuildに以下のオプションを指定したらCudaCompileを並列実行してくれる様になりませんか?

/maxcpucount[:number] もしくは /m[:number]

MSbuildでの同時実行プロセス数は、maxcpucount無しの場合は規定値で1、maxcpucountを値の指定無しで使うとプロセッサの数で実行、となっています。

純粋に各工程一つずつのパフォーマンスを計測する場合は逐次実行の方が良いのかもしれませんが。

Re: 余談 (MSBuildでビルド~)

コメントありがとうございます。

明示的に/mを指定してあげる必要があるのですね。教えていただいたように、/mを使うとVisual Studioから実行した際と同じように並列でコンパイルできました。

パフォーマンスレポート自体はCPU時間のようなもののようで、大きな違いはなかったですが、体感的にはかなり速くなりました。
プロフィール

rigaya

Author:rigaya
アニメとか見たり、エンコードしたり。
連絡先(@を半角にしてください!)
rigaya34589@live.jp
github

最新記事
最新コメント
カテゴリ
月別アーカイブ
カウンター
検索フォーム
いろいろ
公開中のAviutlプラグインとかのダウンロード

○Aviutlプラグイン
x264guiEx 2.xx (ミラー)
- x264を使用したH264出力
- x264guiExの導入>
- x264.exeはこちら>

x265guiEx (ミラー)
- x265を使用したH.265/HEVC出力
- x265.exeはこちら>

QSVEnc + QSVEncC (ミラー)
- QuickSyncVideoによるH264出力
- QSVEncCはコマンドライン版
- QSVEncC 導入/使用方法>
- QSVEncCオプション一覧>

NVEnc + NVEncC (ミラー)
- NVIDIAのNVEncによるH264出力
- NVEncCオプション一覧>

VCEEnc + VCEEncC (ミラー)
- AMDのVCEによるH.264出力
- VCEEncCオプション一覧>

svtAV1guiEx (ミラー)
- SVT-AV1によるAV1出力

ffmpegOut (ミラー)
- ffmpeg/avconvを使用した出力

自動フィールドシフト (ミラー)
- SSE2~AVX2による高速化版
- オリジナル: aji様

エッジレベル調整MT (ミラー)
- エッジレベル調整の並列化/高速化
- SSE2~AVX対応
- オリジナル: まじぽか太郎様

バンディング低減MT (ミラー)
- SSE2~AVX2による高速化版
- オリジナル: まじぽか太郎様

PMD_MT (ミラー)
- SSE2~FMA3による高速化版
- オリジナル: スレ48≫989氏

透過性ロゴ (ミラー)
- SSE2~FMA3によるSIMD版
- オリジナル: MakKi氏

AviutlColor (ミラー)
- BT.2020nc向け色変換プラグイン
- BT.709/BT.601向けも同梱

○その他
x264afs (ミラー)
- x264のafs対応版

aui_indexer (ミラー使い方>)
- lsmashinput.aui/m2v.auiの
 インデックス事前・一括生成

auc_export (ミラー使い方>)
- Aviutl Controlの
 エクスポートプラグイン版
 エクスポートをコマンドから

aup_reseter (ミラー)
- aupプロジェクトファイルの
 終了フラグを一括リセット

CheckBitrate (ミラー, 使い方, ソース)
- ビットレート分布の分析(HEVC対応)

チャプター変換 (ミラー使い方>)
- nero/appleチャプター形式変換

エッジレベル調整 (avisynth)
- Avisynth用エッジレベル調整

メモリ・キャッシュ速度測定
- スレッド数を変えて測定

○ビルドしたものとか
L-SMASH (ミラー)
x264 (ミラー)
x265 (ミラー)

○その他
サンプル動画
その他

○読みもの (ミラー)
Aviutl/x264guiExの色変換
動画関連ダウンロードリンク集
簡易インストーラの概要

○更新停止・公開終了
改造版x264gui
x264guiEx 0.xx
RSSリンクの表示
リンク
QRコード
QR