CUDA in WSL2を試す
なんとWSL2でCUDAが使えるようになったらしい。
最近NVEncをLinuxでもコンパイル・実行できるようにしたので、WSL2からNVEncが使えるようになるとWindows上で手軽にいろいろなLinuxでのテストができる、ということで、「WSL2からCUDAが使えるとはなんと素晴らしい、ならもちろんNVENCも使えるよね!」という大雑把な甘い考えで、やってみたけど、ちょっとうまくいかなかったというお話。
なにか見落としてるのか、そもそも未対応なのか。
今回結局うまくいかなかったけど、とりあえず記録として残しておく。
CUDA in WSL2の導入
※注意点:現時点では、これを試すにはWindows10のInsiderビルドが必要です。予期せず不具合を踏んだりするとなにが起こるかわからないので、試す場合にはどうなってもいい環境でお試しください。
わたしの場合は、データとかなにも入っていない、OSがおかしくなっても「まあOS再インストールするだけで済むよね」という環境でやっています。
0. 環境
今回の環境は、下記の通り。
Win10 x64 20150
Ryzen R7 3700X
GTX1080
1. Insider Buildを有効
Windows Insuder Buildを使用するには、まずアカウントの登録が必要。
その後、「設定」→「更新とセキュリティ」→「Windows Insider Program」から、Insider Programを有効にする。その際、Fast Ringを選択。

この状態でWindows Updateをすると最新のInsiderビルドを取得できる。Update後、Windowsのバージョンが、20145以上になっているのを確認。 (winver.exe)

2. WSL2を実行する環境整備
「Windowsの機能の有効化と無効化」で「Hyper-V」と「Linux用Windowsサブシステム」を有効にして、再起動。
(「Hyper-V」は必要なのかよくわからないけど、とりあえず有効にしておいた)

3. CUDA in WSL2用のドライバのWindowsへのインストール
WSL2でCUDAを使用するには、現時点では専用のNVIDIAのドライバをWindowsにインストールする必要があるようだ。このページからダウンロードできるドライバをインストールする。
このドライバをいれておくことで、その後WSL2にインストールするLinux環境にも勝手にドライバがインストールされるみたい。なので、Linux側ではドライバはインストールしなくていいし、逆にドライバを自分で入れてしまうとWSL2用のドライバを上書きしてしまって、正常にCUDAが動作しなくなる点に注意。
4. Ubuntuを導入
これは普通にWindows Storeからインストールする。ここでは、Ubuntu 18.04 LTSを入れてみる。

まず、WSL2であること(WSL1でないこと)を確認する。(wsl -l -v)

また、WSLのLinux Kernelのバージョンを確認する。(wsl cat /proc/version)

CUDA in WSL2には、現時点では4.19.121以降が必要みたい。このバージョン未満の場合は、Windows Updateで「Windows更新時に他のMicrosoft製品のUpdateを受け取る」にチェックが入っているとを確認し(下図)、再度更新チェックするとよいとのこと。

5. 開発環境の導入
これは普通のUbuntuと同じ。
sudo apt update
sudo apt upgrade
sudo apt install build-essential git nasm yasm
6. CUDA Toolkitのインストール
WSL2でCUDAを使うというテーマなのに、肝心のCUDA ToolkitのインストールとビルドについてがNVIDIAのWSL2関係のドキュメントにはなぜか書いてなくて戸惑ったのだけど、まあ1点だけ気を付ければ(ドライバはインストールしない)、あとは普段通りやるだけだから書くまでもないでしょ、ということなのかもしれない。
まあ、Ubuntu 18.04ならインストーラを使うのがたぶん簡単なので、下記を実行。
wget http://developer.download.nvidia.com/compute/cuda/10.2/Prod/local_installers/cuda_10.2.89_440.33.01_linux.run
sudo sh cuda_10.2.89_440.33.01_linux.run
インストーラを実行するとインストールするコンポーネントを選択する画面が出るけど、ここで重要な注意点として、ドライバのチェックを外す。これは先ほど書いたように、WSL2 with CUDAの環境にはすでにWSL2用のドライバが入っていて、これを使わないといけないためで、CUDA Toolkitインストーラ付属のドライバをインストールしないようにする。

CUDAのインストールが終わると、CUDAのサンプルプログラム等をビルド・実行できるようになる。
deviceQueryをビルドして実行するとこんな感じ。

CUDA APIから、GTX1080をちゃんと認識できている!素晴らしい!
※なお、現状WSL2上ではlibnvml関係は未対応ということなので、これに依存するnvidia-smi等も使えない。
というわけで、CUDAはちゃんと使えることがわかった、ということで次はNVENC。
7. NVEncに必要なライブラリの導入
NVEncのビルドには、ffmpeg 4系が必要なので、これを導入する。
sudo add-apt-repository ppa:jonathonf/ffmpeg-4
sudo apt update
sudo apt install ffmpeg \
libavcodec-extra58 libavcodec-dev libavutil56 libavutil-dev libavformat58 libavformat-dev \
libswresample3 libswresample-dev libavfilter-extra7 libavfilter-dev libass9 libass-dev
8. NVEncのビルド
WSL2用のlibcuda.soは/usr/lib/wsl/libというところに入っていて、g++でリンクさせようとすると、見つからないとか文句を言われるので、面倒なのでcudaの通常のライブラリパス(${CUDA_PATH}/lib64)にリンクを貼っておく。(nvccでリンクする以外でもっといい方法は???)
sudo ln -f -s /usr/lib/wsl/lib/libcuda.so /usr/local/cuda/lib64/libcuda.so
これであとはビルドするだけ。
git clone https://github.com/rigaya/NVEnc --recursive
cd NVEnc
./configure
make -j16
問題なくビルドは成功するが、実行するとエラー…。(泣

HWデコードに必要なlibnvcuvid.soがないというエラー。ついでにHWエンコードに必要なlibnvidia-encode.so もないのであった。
見つけられてないだけではないか、本当にないのかと思って探しても、たしかにない。例えばcuda関係のライブラリのディレクトリを見てみてもやっぱりない。

ちなみに、最後の悪あがきとして乱暴にlibnvcuvid.soとlibnvidia-encode.soをドライバ440のものから無理やり導入してみたりしたが、さすがに動作しなかった(エンコーダ初期化時に異常終了)。
無念
もともと、NVIDIA関係のライブラリはドライバに収録されているものとCUDA Toolkitに収録されているものがあるが、libnvcuvid.soとlibnvidia-encode.soはもちろん通常はドライバに収録されている。
WSL2用のドライバ収録のライブラリは、/usr/lib/wsl/libにあるっぽいので、ここにはlibcuda.soのみ(上図)ということは、やはり未対応なのだろうか?
NVIDIAのWSL2関係のドキュメントのKnown Issues等にも言及はないので、よくわからない。
まあそもそもNVDECとNVENCはCUDAの一部なのかもどうかも微妙だし、なにか見落としているのかもしれない。
うーん。
そもそもCUDA in WSL2はDeep Learning向けだって? はっはっは。 いやいやそれよりエンコードでしょ(暴論
最近NVEncをLinuxでもコンパイル・実行できるようにしたので、WSL2からNVEncが使えるようになるとWindows上で手軽にいろいろなLinuxでのテストができる、ということで、「WSL2からCUDAが使えるとはなんと素晴らしい、ならもちろんNVENCも使えるよね!」という
なにか見落としてるのか、そもそも未対応なのか。
今回結局うまくいかなかったけど、とりあえず記録として残しておく。
CUDA in WSL2の導入
※注意点:現時点では、これを試すにはWindows10のInsiderビルドが必要です。予期せず不具合を踏んだりするとなにが起こるかわからないので、試す場合にはどうなってもいい環境でお試しください。
わたしの場合は、データとかなにも入っていない、OSがおかしくなっても「まあOS再インストールするだけで済むよね」という環境でやっています。
0. 環境
今回の環境は、下記の通り。
Win10 x64 20150
Ryzen R7 3700X
GTX1080
1. Insider Buildを有効
Windows Insuder Buildを使用するには、まずアカウントの登録が必要。
その後、「設定」→「更新とセキュリティ」→「Windows Insider Program」から、Insider Programを有効にする。その際、Fast Ringを選択。

この状態でWindows Updateをすると最新のInsiderビルドを取得できる。Update後、Windowsのバージョンが、20145以上になっているのを確認。 (winver.exe)

2. WSL2を実行する環境整備
「Windowsの機能の有効化と無効化」で「Hyper-V」と「Linux用Windowsサブシステム」を有効にして、再起動。
(「Hyper-V」は必要なのかよくわからないけど、とりあえず有効にしておいた)

3. CUDA in WSL2用のドライバのWindowsへのインストール
WSL2でCUDAを使用するには、現時点では専用のNVIDIAのドライバをWindowsにインストールする必要があるようだ。このページからダウンロードできるドライバをインストールする。
このドライバをいれておくことで、その後WSL2にインストールするLinux環境にも勝手にドライバがインストールされるみたい。なので、Linux側ではドライバはインストールしなくていいし、逆にドライバを自分で入れてしまうとWSL2用のドライバを上書きしてしまって、正常にCUDAが動作しなくなる点に注意。
4. Ubuntuを導入
これは普通にWindows Storeからインストールする。ここでは、Ubuntu 18.04 LTSを入れてみる。

まず、WSL2であること(WSL1でないこと)を確認する。(wsl -l -v)

また、WSLのLinux Kernelのバージョンを確認する。(wsl cat /proc/version)

CUDA in WSL2には、現時点では4.19.121以降が必要みたい。このバージョン未満の場合は、Windows Updateで「Windows更新時に他のMicrosoft製品のUpdateを受け取る」にチェックが入っているとを確認し(下図)、再度更新チェックするとよいとのこと。

5. 開発環境の導入
これは普通のUbuntuと同じ。
sudo apt update
sudo apt upgrade
sudo apt install build-essential git nasm yasm
6. CUDA Toolkitのインストール
WSL2でCUDAを使うというテーマなのに、肝心のCUDA ToolkitのインストールとビルドについてがNVIDIAのWSL2関係のドキュメントにはなぜか書いてなくて戸惑ったのだけど、まあ1点だけ気を付ければ(ドライバはインストールしない)、あとは普段通りやるだけだから書くまでもないでしょ、ということなのかもしれない。
まあ、Ubuntu 18.04ならインストーラを使うのがたぶん簡単なので、下記を実行。
wget http://developer.download.nvidia.com/compute/cuda/10.2/Prod/local_installers/cuda_10.2.89_440.33.01_linux.run
sudo sh cuda_10.2.89_440.33.01_linux.run
インストーラを実行するとインストールするコンポーネントを選択する画面が出るけど、ここで重要な注意点として、ドライバのチェックを外す。これは先ほど書いたように、WSL2 with CUDAの環境にはすでにWSL2用のドライバが入っていて、これを使わないといけないためで、CUDA Toolkitインストーラ付属のドライバをインストールしないようにする。

CUDAのインストールが終わると、CUDAのサンプルプログラム等をビルド・実行できるようになる。
deviceQueryをビルドして実行するとこんな感じ。

CUDA APIから、GTX1080をちゃんと認識できている!素晴らしい!
※なお、現状WSL2上ではlibnvml関係は未対応ということなので、これに依存するnvidia-smi等も使えない。
というわけで、CUDAはちゃんと使えることがわかった、ということで次はNVENC。
7. NVEncに必要なライブラリの導入
NVEncのビルドには、ffmpeg 4系が必要なので、これを導入する。
sudo add-apt-repository ppa:jonathonf/ffmpeg-4
sudo apt update
sudo apt install ffmpeg \
libavcodec-extra58 libavcodec-dev libavutil56 libavutil-dev libavformat58 libavformat-dev \
libswresample3 libswresample-dev libavfilter-extra7 libavfilter-dev libass9 libass-dev
8. NVEncのビルド
WSL2用のlibcuda.soは/usr/lib/wsl/libというところに入っていて、g++でリンクさせようとすると、見つからないとか文句を言われるので、面倒なのでcudaの通常のライブラリパス(${CUDA_PATH}/lib64)にリンクを貼っておく。(nvccでリンクする以外でもっといい方法は???)
sudo ln -f -s /usr/lib/wsl/lib/libcuda.so /usr/local/cuda/lib64/libcuda.so
これであとはビルドするだけ。
git clone https://github.com/rigaya/NVEnc --recursive
cd NVEnc
./configure
make -j16
問題なくビルドは成功するが、実行するとエラー…。(泣

HWデコードに必要なlibnvcuvid.soがないというエラー。ついでにHWエンコードに必要なlibnvidia-encode.so もないのであった。
見つけられてないだけではないか、本当にないのかと思って探しても、たしかにない。例えばcuda関係のライブラリのディレクトリを見てみてもやっぱりない。

ちなみに、最後の悪あがきとして乱暴にlibnvcuvid.soとlibnvidia-encode.soをドライバ440のものから無理やり導入してみたりしたが、さすがに動作しなかった(エンコーダ初期化時に異常終了)。
無念
もともと、NVIDIA関係のライブラリはドライバに収録されているものとCUDA Toolkitに収録されているものがあるが、libnvcuvid.soとlibnvidia-encode.soはもちろん通常はドライバに収録されている。
WSL2用のドライバ収録のライブラリは、/usr/lib/wsl/libにあるっぽいので、ここにはlibcuda.soのみ(上図)ということは、やはり未対応なのだろうか?
NVIDIAのWSL2関係のドキュメントのKnown Issues等にも言及はないので、よくわからない。
まあそもそもNVDECとNVENCはCUDAの一部なのかもどうかも微妙だし、なにか見落としているのかもしれない。
うーん。
そもそもCUDA in WSL2はDeep Learning向けだって? はっはっは。 いやいやそれよりエンコードでしょ(暴論
スポンサーサイト