Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
513
Help us understand the problem. What are the problem?
@ksasaki

待ってました CUDA on WSL 2

最新情報 (2021-09-04 時点)

エヌビディアの佐々木です。

2020 年 6 月にこの記事を書いて以来、Windows Insider Preview や NVIDIA ドライバの新しいビルドが出たタイミングなどで記事を更新してきましたが、あちこちに注釈が増えて読みづらくなってきたので、今後はこの「最新情報」セクションに新しい情報を集約しようと思います。あと、更新履歴は記事末尾へ送りました。
こちらも合わせてご覧ください: CUDA on WSL User Guide の Release Notes

私が動作を確認したバージョン

  • Windows Insider Preview のビルド: 22000.176 (話題の Windows 11 です)
  • NVIDIA ドライバ: 510.06
    • nvidia-smi コマンドの GPU-Util 列が "N/A" になってしまう問題あり。開発チームに確認中。
  • 実行した NGC コンテナイメージ

Beta チャネルで使えるようになりました

私が試した Windows Insider Preview のビルド 22000.176 は Windows 11 のプレビューなわけですが、10 月 5 日の Windows 11 正式リリースを控えて、CUDA on WSL 2 が使えるこのビルドが Beta チャネルにも降ってくるようになりました。Dev チャネルへの参加を躊躇していた方も、これを機会に GA より一足早く CUDA on WSL 2 を試してみませんか!

Docker Desktop for Windows の WSL 2 バックエンドについて

私は以前、WSL 2 でのコンテナ実行環境として、Docker Desktop とその WSL 2 バックエンドを使う方法を紹介しました。これは確かに動作するのですが、NVIDIA Container Toolkit は、これをまだ正式にはサポートしていません。

CUDA on WSL 2 のドキュメントにも下記のようにありますので、サポートされる方式のみ紹介するように、この文書も更新しました。

Note that NVIDIA Container Toolkit has not yet been validated with Docker Desktop WSL 2 backend. Use Docker-CE for Linux instead inside your WSL 2 Linux distribution.

ここから本編

※ ここからは、2020 年 6 月時点の古い内容が部分的に残っています。

2020 年 5 月の BUILD カンファレンスで発表されたとおり、WSL 2 で CUDA が使えるようになったので、早速試してみました。手順は簡単で、私がこんな駄文にまとめる意味もないくらいですが、マイクロソフトとエヌビディア双方にドキュメントが分散していますので、かつてはマイクロソフトで Services for UNIX (SFU) / Subsystem for UNIX-based Applications (SUA) を、今はエヌビディアで GPU を売っている私が何か書いてみるのは一つの役割と言えましょう。え、そうでもない?

CUDA on WSL 2 の環境構築 (Windows 側)

では、さっさと環境を作ってしまいましょう。手順の概略は CUDA on WSL User Guide に載っています。私が試した下記の内容もこのガイドに沿っています。

Windows 10 Insider Preview Build 20150 (以降) のインストール

良く訓練された Windows ユーザーなら、Insider Preview の Fast Ring (改め、Dev Channel) に参加しているはずなので、今朝 (日本では 2020 年 6月 18 日) 目が覚めたらもう Build 20150.1000 が降ってきていたはずです。インストールしましょう。

※ Insider Preview はちょっとなぁ…という方、是非「Boot from VHD 機能で Windows Insider Preview を安全に試す」もご覧ください。

Insider Preview に参加していないユーザーにとっては、これに参加してインストールするまでが一番時間のかかるプロセスかもしれません。下図のように、Windows 10の「設定」から Windows Insider Preview の「ファスト」に参加してください。

ダウンロードとインストールにはそこそこ長い時間がかかります。どうにかそれが終わったら、コマンドプロンプトで ver コマンドを実行し、確かに 20150 (以降) がインストールされていることを確認しましょう。

C:\WINDOWS\system32>ver

Microsoft Windows [Version 10.0.21301.1000]

NVIDIA Drivers for CUDA on WSL のインストール

ホスト側 Windows の準備ができたら、次に NVIDIA ドライバをインストールします。このドライバ、WSL 2 の Linux カーネル側 ではなく、ホストの Windows にインストールします。 CUDA on Windows Subsystem for Linux (WSL) - Public Preview のページから Get CUDA Driver を辿ってドライバのダウンロードページアクセスし、GeForce Driver か Quadro Driver のいずれかを自分の環境に合わせてダウンロードしてください。

「NVIDIA Developer Program Membership Required」と表示されたら「Login」してください。

え、アカウントをお持ちでない?!「Join now」お願いします。

インストール作業自体は、Windows へ NVIDIA ドライバをインストールするいつもの手順と変わりませんので、詳細は割愛します。私は全てデフォルトの選択肢で次へ次へと進みました。

インストール完了後は、Windows の再起動が必要です。

WSL 2 のインストール

以前はここで、「『仮想マシン プラットフォーム』の有効化」と「Linux ディストリビューションのインストール」という手順を紹介していましたが、ビルド 20262 以降では、WSL 2 のインストールが非常に簡単になっています。

例えば、Ubuntu-18.04 をインストールするのであれば、管理者権限で起動した Power Shell かコマンド プロンプトで、次のコマンドを実行するだけです。

wsl --install -d Ubuntu-18.04

このコマンドで、以下の作業が実行されます。

  • 「Linux 用 Windows サブシステム (WSL)」および「仮想マシン プラットフォーム」を有効にする
  • 最新の Linux カーネルをダウンロードしてインストールする
  • WSL 2 を既定値として設定する
  • 指定の Linux ディストリビューション (この場合 Ubuntu 18.04) をダウンロードしてインストールする

Windows 側での作業は以上です。これで、WSL 2 が使えるようになりました。Windows のスタートメニューから、先ほどインストールした Linux ディストリビューションのアイコンをクリックするなどして、シェルを起動すればそこはおなじみの Linux 環境です。

あとは通常の Linux 環境と (おおむね) 同様に GPU を使えるのですが、下記のうちどちらの方法を使うかで必要な準備が変わってきますので、簡単に説明します。

  • WSL 2 上で直接 CUDA プログラムを実行する。
  • WSL 2 上で Docker と NVIDIA Container Toolkit を使って Docker コンテナで GPU を使う。

CUDA Toolkit のインストール

コンテナを使わずに、直接 CUDA プログラムを実行する場合は、WSL 2 上の Linux に CUDA Toolkit をインストールすれば良いのですが、重要な注意点があります。

Linux 用の NVIDIA ドライバをインストールしてはいけません

つい、いつもの癖で sudo apt-get install cuda などとやってしまいそうになりますが、 cuda-toolkit-<version> パッケージを指定してください。Ubuntu-18.04 に CUDA-11.2 をインストールする例は次の通りです。

sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
sudo sh -c 'echo "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 /" > /etc/apt/sources.list.d/cuda.list'
sudo apt-get update
sudo apt-get install -y cuda-toolkit-11-2

なお、CUDA Toolkit のバージョン 11.1 からは、ディストリビューションの選択肢に "WSL-Ubuntu" が増えています。WSL 2 で Ubuntu を利用する場合は、こちらを選択しても OK です。この場合、ネイティブ Linux と同様に "cuda" パッケージをインストールすれば OK です。

CUDA 11.4.1 で、ディストリビューションとして "WSL-Ubuntu" を、Installer Type に "dev (local)" を指定した場合のコマンドは次の通りです。

wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/11.4.1/local_installers/cuda-repo-wsl-ubuntu-11-4-local_11.4.1-1_amd64.deb
sudo dpkg -i cuda-repo-wsl-ubuntu-11-4-local_11.4.1-1_amd64.deb
sudo apt-key add /var/cuda-repo-wsl-ubuntu-11-4-local/7fa2af80.pub
sudo apt-get update
sudo apt-get -y install cuda

CUDA Toolkit のインストール完了後は、動作確認の意味で /usr/local/cuda/samples 配下にあるサンプル プログラムをビルド・実行してみるのも良いでしょう。下図は、私の PC で deviceQuery プログラムを実行してみたところです。

ちゃんと認識されていますね!

コンテナー実行環境の構築

そもそも私が CUDA on WSL 2 を待っていたのは、NGC のコンテナーイメージを Windows 上で手軽に実行したいからです。普段使っている PC は Windows 10 と Ubuntuのデュアルブートにしてあるのですが、コンテナーで GPU を使うために Ubuntu にブートし直すのは面倒だなぁ、ということが結構あるわけです。

というわけで WSL 2 でのコンテナ実行環境を構築しますが、現時点では方法が二つあります。

  • WSL 2 上の Linux に Docker と NVIDIA Container Toolkit をインストールする
  • Docker Desktop とその WSL 2 バックエンドを使う (未サポート)

後者は、動作はしますが、現時点 (2021 年 9 月) では正式にサポートされていません。それゆえ、ここでは前者のみ紹介します。

WSL 2 上の Linux への Docker のインストール

Docker 公式の便利スクリプトで、最新の安定版をすぐにインストールできます。

curl https://get.docker.com | sh

この時、

WSL DETECTED: We recommend using Docker Desktop for Windows.

と警告されますが、このメッセージは無視して進めてください。

WSL 2 上の Linux への NVIDIA Container Toolkit のイントール

ユーザーガイドにあるコマンドを一つずつ打つのもダルいので、次のようなシェルスクリプトにして実行しました。

#!/bin/sh

distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
curl -s -L https://nvidia.github.io/libnvidia-container/experimental/$distribution/libnvidia-container-experimental.list | sudo tee /etc/apt/sources.list.d/libnvidia-container-experimental.list

sudo apt-get update
sudo apt-get install -y nvidia-docker2
sudo usermod -aG docker $USER

最後に、Docker デーモンを再起動しておきましょう。

sudo service docker restart

以上で Linux 側の作業は終了です。ドライバーをインストールする作業がない分、通常の Linux で GPU 対応コンテナ環境をセットアップするよりも簡単なぐらいですね。

なお、ここでインストールした NVIDIA Container Toolkit は、かつて NVIDIA Docker と呼ばれていたもので、コンテナー内で GPU を利用するために必要なモジュールです。詳しくはこちらの記事をご覧ください。

NGC のコンテナーイメージを動かしてみる

早速 NGC のコンテナイメージを試してみましょう。私の PC には Ampere アーキテクチャの GPU が載っていますので、その Tensor コアを活用すべく、以前「NGC のコンテナーイメージで AMP を試してみる」に書いた TensorFlow イメージを動かしてみました。

WSL 2 の Ubuntu を起動し、次のコマンドを実行してコンテナを起動します。

docker run --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 --gpus all --rm -it nvcr.io/nvidia/tensorflow:21.08-tf2-py3

※ ここで一つご注意。コンテナ起動時に、下記の警告が出力されますが、これは誤ったメッセージで、修正予定です。実際にはちゃんと GPU が認識されています。

WARNING: The NVIDIA Driver was not detected.  GPU functionality will not be available.
   Use 'nvidia-docker run' to start this container; see
   https://github.com/NVIDIA/nvidia-docker/wiki/nvidia-docker .

コンテナが起動したら、ResNet-50 をトレーニングベンチマークモード (学習データをその場で生成するモード) で実行します。AMP (Automatic Mixed Precision) を有効にするため、--precision=fp16 も付けてあります。

/workspace/nvidia-examples/cnn/resnet.py \
  --export_dir=/tmp \
  --display_every=10 \
  --num_iter=100 \
  --iter_unit=batch \
  --batch_size=128 \
  --precision=fp16

下図の通り、普通に動きます。また、以前はこのシンプルなベンチマークテストでも、CUDA on WSL 2 の性能はネイティブ Linux に劣っていましたが、NVIDIA ドライバ 465.42 では大幅に性能が向上し、ネイティブと遜色ないレベルに近づいています。

※ なお、WSL は標準のコンソール以外にも様々なソフトウェアでアクセスできますが、この例で私が使っているのは MobaXterm です。WSL に対応しているだけでなく、X サーバーも内蔵されている便利なやつです。リモートもローカルもこれ一つでOK.

nvidia-smi コマンド

NVIDIA ドライバ 465.42 以降では、CUDA on WSL 2 で NVML (NVIDIA Management Library) がサポートされました。これによって、おなじみの nvidia-smi コマンドがついに WSL 2 で使えるようになりました!(nvidia-smi は NVML を使って GPU の情報を得ているのです)

ただし、 今のところ nvidia-smi コマンドは /usr/bin に配置されていませんので、実行するには下記の準備が必要です。

$ sudo cp /usr/lib/wsl/lib/nvidia-smi /usr/bin
$ sudo chmod +x /usr/bin/nvidia-smi

そして、残念ながら現時点では、 nvidia-smi の動作には少し問題があります。肝心の GPU 使用率が、「ERR!」となって取得できません。

$ nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 465.00       Driver Version: 465.42       CUDA Version: 11.3     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  GeForce RTX 3080    Off  | 00000000:33:00.0  On |                  N/A |
| 30%   34C    P8    24W / 320W |    595MiB / 10240MiB |    ERR!      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
|   1  GeForce RTX 3070    Off  | 00000000:34:00.0 Off |                  N/A |
|  0%   34C    P8     6W / 220W |    149MiB /  8192MiB |    ERR!      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

この問題、開発チームは認識済みで修正の予定ですが、当面の回避策としては、今まで通り、Windows 側で nvidia-smi.exe を実行する手があります。私がよく使うのは、 --loop--query-gpu オプションを使って、行単位でログを出力し続ける方法です。原始的ですが、実用的ですよ。

C:\WINDOWS\system32>nvidia-smi --loop=2 -i 0  --format=csv --query-gpu=timestamp,utilization.gpu,clocks.sm,power.draw,temperature.gpu
2021/01/31 00:11:48.294, 92 %, 1949 MHz, 278.93 W, 58
2021/01/31 00:11:50.306, 88 %, 1949 MHz, 283.70 W, 59
2021/01/31 00:11:52.317, 87 %, 1950 MHz, 280.65 W, 59
2021/01/31 00:11:54.329, 78 %, 1952 MHz, 277.86 W, 59
2021/01/31 00:11:56.342, 84 %, 1948 MHz, 277.33 W, 60
2021/01/31 00:11:58.354, 89 %, 1949 MHz, 283.92 W, 61

「生の Linux」とは違うところも

先ほどの例のように、CUDA のサンプルや NGC のコンテナーイメージを動かすだけならあまり違和感もなく、別の Linux マシンにログインして動かしているのと区別が付かないぐらいです。しかし、通常の Linux とは異なる不思議な点もいくつかあります。

例えば、

lspci しても GPU は見当たらず…

# lspci
8375:00:00.0 SCSI storage controller: Red Hat, Inc. Virtio filesystem (rev 01)
86cb:00:00.0 SCSI storage controller: Red Hat, Inc. Virtio filesystem (rev 01)
a609:00:00.0 SCSI storage controller: Red Hat, Inc. Virtio filesystem (rev 01)
b246:00:00.0 SCSI storage controller: Red Hat, Inc. Virtio filesystem (rev 01)
b7b6:00:00.0 3D controller: Microsoft Corporation Device 008e
bd73:00:00.0 SCSI storage controller: Red Hat, Inc. Virtio filesystem (rev 01)

いつも存在するデバイスファイル等もありません。

# ls -l /dev/nvidia*
ls: cannot access '/dev/nvidia*': No such file or directory
# ls -l /proc/driver/nvidia
ls: cannot access '/proc/driver/nvidia': No such file or directory

そう、WSL 2 の Linux には、PCI デバイスとしての GPU は直接見えていません。NVIDIA ドライバを Windows にだけインストールしたことからもわかるように、GPU は Windows のデバイスとして管理されており、WSL 2 の Linux からは、それを /dev/dxg というデバイスを通じて利用します。この /dev/dxg は所謂準仮想化デバイスです。ホストの Windows と、WSL の軽量ユーティリティ VM は、VMBus という仮想バスで接続されており、Linux 側での /dev/dxg への操作は、 dxgkrnl という準仮想化ドライバによって VMBus 経由でホストの GPU へ伝わります。


Announcing CUDA on Windows Subsystem for Linux 2 より

この、[ゲストの準仮想化デバイス]-[VMBus]-[ホストのデバイス] という仕組みは、Windows のハイパーバイザである Hyper-V が当初から備えているもので、ディスクや NIC のようなデバイスを完全にエミュレーションするのではなく、仮想環境に最適化した準仮想化デバイスとして実装するために利用されているものです。それが今回は、Windows の GPU を WSL 側で使うために活用されているわけですね。

※ ここで登場した Linux カーネル内の dxgkrnl は、従来から存在する Windows の DirectX グラフィックスカーネルと同じ名称ではありますが、新たに Linux 用に実装されたものだそうです。
ソースコードはこちら: WSL2-Linux-Kernel/drivers/gpu/dxgkrnl/

下記のように「Windows のとは共通点は何もない」と強調されていますね。IP 汚染の懸念はないよ、ということでしょう。

Although they share a name, the version of dxgkrnl inside of the Linux kernel is a clean room implementation of a Linux GPU driver based on our GPU-PV protocol and doesn’t share anything else in common with its similarly named Windows counterpart.

出典: DirectX is coming to the Windows Subsystem for Linux

制限事項

さて、実際に試せるようになった CUDA on WSL 2 ですが、

  • Windows Insider Preview で提供
  • NVIDIA Driver もプレビュー版

という段階ですから、まだまだ荒削りな部分、未実装の部分があります。ユーザーガイドの制限事項からいくつか抜き出してみると、

  • デバッガやプロファイラは未サポート
  • NVIDIA Container Toolkit では、docker run 時に --gpus all のみをサポート。複数の GPU がある場合に、一部に絞ってコンテナに使わせることができない。

などです。この記事を最初に書いたときと比べると、制限事項が減ってきました!

まとめ

  • Windows 10 の WSL 2 でついに CUDA が使えるようになりました。 (なり始めました)
  • NGC の TensorFlow コンテナイメージなどは既に普通に動きます。
  • Windows Insider Preview と、NVIDIA Developer Program へ是非登録をお願いします。
  • 465.42 で NVML を実装。結果的に nvidia-smi コマンドも動作可能に!
  • まだ、いくつか制限事項もありますが、ぜひお試しの上フィードバックを。

お楽しみ CUDA さい!

関連情報

Announcing CUDA on Windows Subsystem for Linux 2
CUDA on WSL User Guide
NVIDIA Drivers for CUDA on WSL
Docker Desktop WSL 2 backend
Announcing Windows 10 Insider Preview Build 20150
The Windows Subsystem for Linux BUILD 2020 Summary
Windows Subsystem for Linux Documentation
Boot from VHD 機能で Windows Insider Preview を安全に試す
Automatic Mixed Precision (AMP) でニューラルネットワークのトレーニングを高速化
NVIDIA Docker って今どうなってるの? (20.09 版)

更新履歴

※ 2021/09/04 NVIDIA ドライバ 510.06 と、WIP ビルド 22000.176に関して追記しました。
※ 2021/07/30 NVIDIA ドライバ 471.21 と、WIP ビルド 22000.100に関して追記しました。
※ 2021/06/30 NVIDIA ドライバ 471.11 と、WIP ビルド 22000.51に関して追記しました。
※ 2021/06/07 NVIDIA ドライバ 470.76 と、WIP ビルド 21390に関して追記しました。
※ 2021/04/08 NVIDIA ドライバ 470.14 で nvidia-smi が動作しない問題が報告されている点を追記しました。
※ 2021/03/12 Windows Insider Preview ビルド 21332 および NVIDIAドライバ 470.05 に合わせて更新しました。(更新履歴は記事末尾へ移しました)
※ 2021/02/05 Docker Desktop の WSL 2 バックエンドが GPU に対応した点を追記しました。
※ 2021/01/31 ビルド 21292 以降と NVIDIA ドライバ 465.42 で、CUDA 11.2 に対応、性能向上、NVML のサポート、nvidia-smi コマンドのサポートなど重要な改善があったので追記しました。
※ 2021/01/03 CUDA 11.2 で CUDA on WSL 2 がうまく動かない問題が確認されたこと等を追記しました。
※ 2020/10/15 CUDA Toolkit インストール時に "WSL-Ubuntu" が選択できるようになった点などを追記しました。
※ 2020/07/27 WSL 2 への CUDA Toolkit インストール時の注意点を追記しました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
513
Help us understand the problem. What are the problem?