Windows 11 で CUDA on WSL2 環境を構築する

WSL 2Linux,Ubuntu,Windows,Windows 11,WSL2

Windows 11のWSL2+Ubuntu 20.04環境にCUDAドライバーやCUDAツールキットをインストールし、WSL2上でCUDAが動くよう環境構築してみました。

CUDAを利用したソフトの開発・利用はWindows側でも可能ですが、Linuxに慣れた方はWSL2のUbuntuでCUDAが利用できた方が便利でしょう。現在は、WSL2のプレビュー版とCUDAドライバーのプレビュー版を利用すればWSL2上でもCUDAが利用可能ですので、その環境構築のしかたをまとめました。

まえがき

「CUDA on WSL」とは

CUDAは、NVIDIAのGeForceなどのGPUで一般的な数値計算をさせる仕組み(GPGPU; General-purpose computing on graphics processing units)です。GPUは、ゲームの3D CGやウィンドウの描画処理を担当しているため、グラフィックス処理に使われるベクトルや行列の演算を得意としています。その特長を生かしてGPUに汎用計算をさせよう、というのがGPGPUです。

「ベクトルや行列の演算が得意」という特長から、画像処理や映像処理(動画のエンコードなど)、CAE(流体シミュレーションなど)、機械学習(ディープラーニングなど)などのアプリケーションで処理速度の向上が見込まれます。

WSLは、Windowsの仮想環境でLinuxディストリビューションを動かす仕組みで、Ubuntuなどのディストリビューションを動かすことができます。VMwareのような仮想PCソフトよりもハードウェアに近い階層でLinuxが動きますので、仮想PCソフトにUbuntuを入れるより高パフォーマンスが望めます。また、WSLはWindows側とLinux側でお互いにディレクトリを参照できるなど、シームレスにWindowsとLinux仮想環境を行き来できます。

CUDAそのものはWindowsにも導入でき、Visual Studioなどで開発することもできますが、応用分野によってはLinuxの方が都合が良いという方もいると思います。そのためにLinuxをデュアルブートでインストールしたり、別の実機を用意したりするのも不便があります。そのような、「普段はWindowsを使っているけど、CUDAを使ったアプリケーションはLinuxで動かしたい」という人は、WSL中でCUDAが使えれば利便性が向上します。それを実現するのが「CUDA on WSL」です。

本記事では、Windows 11におけるCUDA on WSLのセットアップ方法を紹介します。

検証環境

本記事は、Windows 11 ProのInsider Preview版(21H2、ビルド22000.71)で動くことを確認しています(恐らく、Windows 10のInsider Previewでも同様と思われます)。プレビュー版での検証ですので、今後手順が変わる可能性があります。ご了承ください。

CUDA on WSLのシステム要件

CUDA on WSLの必須要件、推奨要件は以下の通りです。

  • Windows 10 Insider PreviewのDevチャンネルで、必須要件はビルド20145以降、推奨はビルド21390以降。もしくはWindows 11。
    ビルド番号はwinverコマンドなどで確認できます。今回の検証環境は、ビルド22000.71です。
  • WSLカーネルのバージョンが4.19.121以降、推奨は5.10.16.3以降。
    恐らく、WSLカーネルバージョンは、Ubuntu中でuname -rしたときの番号だと思います。今回の検証環境では5.10.43.3です。
  • Pascal世代以降のGeForce、Quadro搭載グラボ。「Pascal世代」は、GeForce GTX 1080などのことです。ただ、本記事ではその一つ前の「Maxwell世代」のGeForce GTX 960M搭載PCを使っています。

記事執筆時点の通常リリース版であるWindows 10 21H1では、CUDA on WSLは利用できません(ツールキットはインストールできますが、実行時にCUDAが利用できません)。じきに通常リリース版でもCUDA on WSLが利用可能になると思いますが、現時点ではWindows Insider Previewに参加する必要があります。

また、WSLカーネルのバージョンが古い方は、コマンドプロンプト(管理者権限)などでwsl --updateをするとアップデートできます。

PCへCUDAドライバーのインストール

はじめに、CUDA on WSLを利用したいPC(Windows側)へ、CUDAドライバーのプレビュー版をインストールします。CUDAドライバーのダウンロードは、「NVIDIA Developer Program Membership」への登録・ログインが必要になります。途中で登録やログインを促すページに移りますので、画面の案内に従って登録・ログインを行ってください。

CUDAドライバー(NVIDIA drivers for WSL with CUDA and DirectML)のダウンロードはこちらから行えます。

このページから「Get CUDA Driver」を押して、お使いのGPU(GeForceかQuadro)の「DOWNLOAD NOW」をクリックします。

恐らくここで「NVIDIA Developer Program Membership」へのログインか登録を促されますので、指示に従います。ログイン後、会員画面の上部の「Now you can continue to download the file: 471.21_gameready_win10-dch_64bit_international.exe」というような表示をクリックするとダウンロードできます。(ファイル名は時期によって変わっている可能性があります)

上部のファイル名をクリックすると、CUDA on WSL対応ドライバーがダウンロードできます

ダウンロードしたら、インストールします。インストール自体はごく普通です。ただし、必要なのはドライバーだけですので、途中の選択肢は「NVIDIA グラフィックス ドライバー」だけで構いません。

GeForce Experienceが不要なら、下の選択肢でOKです

WSL2とUbuntuのセットアップ

CUDA on WSLは、WSL2上のUbuntuなどで動作します。そのため、まだWSL2関連のセットアップが済んでいない方は、先にWSL2とUbuntuなどのディストリビューションをインストールしてください。

こちらの「WSL2 と Ubuntu 20.04 を インストール」の項(下図の画面まで)をしておいてください。この後の説明は、「Ubuntu」か「Ubuntu-20.04」をインストールしたことを想定して進めます。

Ubuntuのユーザーアカウントの作成の所まで済ませておいてください。

CUDA on WSLをセットアップ

続いて、WSL2上のUbuntu側で、CUDAツールキットのインストールを行います。

関連ソフトのインストールや設定を行うシェルスクリプトを作成しましたので、それを使って自動セットアップしたい方は、このまま次項に進んでください。

シェルスクリプトではなく、一つ一つ手動でコマンドを実行しながらセットアップを進めたい方は、次項を飛ばして「手動セットアップ」へ進んでください。

シェルスクリプトで自動セットアップ

Windows TerminalなどからUbuntuを起動して、CUDA on WSLの設定を行っていきます。各種設定を行うBashスクリプトを作成しましたので、こちらを実行してください。後ほどダウンロードリンクを紹介します。

#!/bin/bash
# Copyright (c) 2021 astherier
# This software is released under the MIT License.
# http://opensource.org/licenses/mit-license.php
#
#install-cuda-on-wsl.sh
#WSL2のUbuntu側で行うCUDA on WSLのセットアップスクリプト
#最終更新:2021/07/17
#https://astherier.com/blog/2021/07/windows11-cuda-on-wsl2-setup/

#CUDAリポジトリ名(DISTRO)とインストールするパッケージ名(APT_INSTALL)を指定してください。
#リポジトリ名を変更した場合、パッケージ名は明示的にCUDAツールキットを指定してください。
#(wsl-ubuntu以外のリポジトリから「cuda」をインストールすると、ディスプレイドライバーまでインストールしようとしてしまうため)
export DISTRO=wsl-ubuntu
export APT_INSTALL=cuda
#export DISTRO=ubuntu2004
#export APT_INSTALL=cuda-toolkit-11-4

#CUDAリポジトリの登録
sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/${DISTRO}/x86_64/7fa2af80.pub
echo "deb http://developer.download.nvidia.com/compute/cuda/repos/${DISTRO}/x86_64 /" | sudo tee /etc/apt/sources.list.d/cuda.list
wget https://developer.download.nvidia.com/compute/cuda/repos/${DISTRO}/x86_64/cuda-${DISTRO}.pin
sudo mv cuda-${DISTRO}.pin /etc/apt/preferences.d/cuda-repository-pin-600

#CUDAツールキットのインストール
sudo apt update && sudo apt -y upgrade
sudo apt install -y ${APT_INSTALL}

#環境変数の設定
cat << 'EOS' >> ~/.profile

#Added by install-cuda-on-wsl.sh
#Ref: https://astherier.com/blog/2021/07/windows11-cuda-on-wsl2-setup/
export PATH=/usr/local/cuda-11.4/bin${PATH:+:${PATH}}
#Added: end

EOS

#サードパーティーライブラリのインストール(任意)
sudo apt install -y g++ freeglut3-dev build-essential libx11-dev libxmu-dev libxi-dev libglu1-mesa libglu1-mesa-dev

#サンプルプログラムのビルド(任意)
cd /usr/local/cuda/samples/1_Utilities/deviceQuery/
sudo make
cd /usr/local/cuda/samples/1_Utilities/bandwidthTest/
sudo make
cd /usr/local/cuda/samples/7_CUDALibraries/simpleCUBLAS/
sudo make
cd /usr/local/cuda/samples/7_CUDALibraries/simpleCUFFT/
sudo make

cd /usr/local/cuda/samples/bin/x86_64/linux/release/

echo "

CUDA on WSLのセットアップが終了しました。
いくつかサンプルをコンパイルしていますので、正常に動くか確認してください。
(例)
$ cd /usr/local/cuda/samples/bin/x86_64/linux/release/
$ ./deviceQuery

"

UbuntuはLinuxですので、上記を「BOMなしUTF-8、改行コードLF」で保存して実行してください。Windows標準のメモ帳では、この形式での保存はできませんので、他のテキストエディタをご利用ください。もしくは、この形式で保存したものをこちらに置いておきましたので、これをご利用ください。
https://astherier.com/static/blog/2021-07-17/install-cuda-on-wsl.sh

これをダウンロードして実行するだけですので、次のコマンドを実行すればOKです。

wget https://astherier.com/static/blog/2021-07-17/install-cuda-on-wsl.sh
source ./install-cuda-on-wsl.sh

しばらく待って、下図のようなメッセージが出たらセットアップ完了です。ダウンロードしたシェルスクリプトはもう使いませんので、削除して構いません。

CUDA on WSLのセットアップが完了しました

引き続いて、(次項を飛ばして)「動作確認」の項へ進んでください。

手動セットアップ

ここでは、前述のシェルスクリプトの解説を兼ねて、手動でインストールする際の手順を紹介します。

はじめに、あとで使う変数を定義しておきます。

DISTRO変数は、NVIDIAのCUDAリポジトリ名の一部で、利用しているディストリビューションの名前を設定します。CUDA on WSL用に「wsl-ubuntu」が用意されていますので、今回はこちらを使います。APT_INSTALL変数は、インストールするパッケージ名を指定します。wsl-ubuntuリポジトリからcudaパッケージをインストールすれば、最新版のCUDAツールキットが導入できます。

export DISTRO=wsl-ubuntu
export APT_INSTALL=cuda

Ubuntu以外のディストリをお使いの場合は、DISTRO変数を適切なディストリ名に変更してください。ディストリ名の一覧はCUDAリポジトリのページで確認できます。DISTRO変数をwsl-ubuntuから変更した場合、「cuda」パッケージをインストールすると、Linux用のディスプレイドライバーまで入れようとしてしまいます。それを防ぐため、DISTRO変数を変更した場合はAPT_INSTALL変数も「cuda-toolkit-11-4」のように、明示的にCUDAツールキットを指定してください(wsl-ubuntuリポジトリの場合は、「cuda」パッケージにディスプレイドライバーは含まれておらず、最新版のCUDAツールキットがインストールされます)。

export DISTRO=ubuntu2004
export APT_INSTALL=cuda-toolkit-11-4

続いて、aptコマンドにNVIDIAのCUDA関連リポジトリを登録します。次のコマンドで、認証鍵の登録、CUDAリポジトリの登録、CUDAリポジトリを優先するためのpinファイル登録を行います。

sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/${DISTRO}/x86_64/7fa2af80.pub
echo "deb http://developer.download.nvidia.com/compute/cuda/repos/${DISTRO}/x86_64 /" | sudo tee /etc/apt/sources.list.d/cuda.list
wget https://developer.download.nvidia.com/compute/cuda/repos/${DISTRO}/x86_64/cuda-${DISTRO}.pin
sudo mv cuda-${DISTRO}.pin /etc/apt/preferences.d/cuda-repository-pin-600

準備が終わりましたので、CUDAツールキットをインストールします。

sudo apt update && sudo apt -y upgrade
sudo apt install -y ${APT_INSTALL}

続いて、CUDAツールキットのbinディレクトリをPATHに追加するよう~/.profileに追記します。

cat << 'EOS' >> ~/.profile

#Added by install-cuda-on-wsl.sh
#Ref: https://astherier.com/blog/2021/07/windows11-cuda-on-wsl2-setup/
export PATH=/usr/local/cuda-11.4/bin${PATH:+:${PATH}}
#Added: end

EOS

こちらは任意ですが、サードパーティーのライブラリもインストールしておきます。nbodyやfluidGLなど、OpenGLを利用したサンプルをビルドする際に必要なものも含まれています。

sudo apt install -y g++ freeglut3-dev build-essential libx11-dev libxmu-dev libxi-dev libglu1-mesa libglu1-mesa-dev

最後に、動作確認用にサンプルプログラムをビルドしておきます。CUDAツールキットのサンプルプログラムは/usr/local/cuda/samples/以下に保存されています。今回は、下記の4つをビルドしてみたいと思います。

cd /usr/local/cuda/samples/1_Utilities/deviceQuery/
sudo make
cd /usr/local/cuda/samples/1_Utilities/bandwidthTest/
sudo make
cd /usr/local/cuda/samples/7_CUDALibraries/simpleCUBLAS/
sudo make
cd /usr/local/cuda/samples/7_CUDALibraries/simpleCUFFT/
sudo make

ちなみに、サンプルプログラムをすべてビルドしたい場合は、下記のコマンドを実行してください。かなり時間がかかりますので、あまりおすすめしません。

cd /usr/local/cuda/samples/
sudo make -j4

以上で、一通りセットアップが終わりました。引き続き、次項の動作確認を行ってください。

動作確認

前項でいくつかCUDAツールキットに入っているサンプルプログラムをコンパイルしていますので、こちらを実行して動作確認をしてみたいと思います。

サンプルプログラムは、次のディレクトリに保存されていますので、移動します。

cd /usr/local/cuda/samples/bin/x86_64/linux/release/

ここでは deviceQuery を実行してみたいと思います。次のように、デバイス情報が表示されたら正常にインストールできています。

$ ./deviceQuery
./deviceQuery Starting...

 CUDA Device Query (Runtime API) version (CUDART static linking)

Detected 1 CUDA Capable device(s)

Device 0: "NVIDIA GeForce GTX 960M"
  CUDA Driver Version / Runtime Version          11.4 / 11.4
  CUDA Capability Major/Minor version number:    5.0
  Total amount of global memory:                 4096 MBytes (4294967296 bytes)
  (005) Multiprocessors, (128) CUDA Cores/MP:    640 CUDA Cores
  GPU Max Clock rate:                            1176 MHz (1.18 GHz)
  Memory Clock rate:                             2505 Mhz
  Memory Bus Width:                              128-bit
  L2 Cache Size:                                 2097152 bytes
  Maximum Texture Dimension Size (x,y,z)         1D=(65536), 2D=(65536, 65536), 3D=(4096, 4096, 4096)
  Maximum Layered 1D Texture Size, (num) layers  1D=(16384), 2048 layers
  Maximum Layered 2D Texture Size, (num) layers  2D=(16384, 16384), 2048 layers
  Total amount of constant memory:               65536 bytes
  Total amount of shared memory per block:       49152 bytes
  Total shared memory per multiprocessor:        65536 bytes
  Total number of registers available per block: 65536
  Warp size:                                     32
  Maximum number of threads per multiprocessor:  2048
  Maximum number of threads per block:           1024
  Max dimension size of a thread block (x,y,z): (1024, 1024, 64)
  Max dimension size of a grid size    (x,y,z): (2147483647, 65535, 65535)
  Maximum memory pitch:                          2147483647 bytes
  Texture alignment:                             512 bytes
  Concurrent copy and kernel execution:          Yes with 4 copy engine(s)
  Run time limit on kernels:                     Yes
  Integrated GPU sharing Host Memory:            No
  Support host page-locked memory mapping:       Yes
  Alignment requirement for Surfaces:            Yes
  Device has ECC support:                        Disabled
  Device supports Unified Addressing (UVA):      Yes
  Device supports Managed Memory:                Yes
  Device supports Compute Preemption:            No
  Supports Cooperative Kernel Launch:            No
  Supports MultiDevice Co-op Kernel Launch:      No
  Device PCI Domain ID / Bus ID / location ID:   0 / 2 / 0
  Compute Mode:
     < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 11.4, CUDA Runtime Version = 11.4, NumDevs = 1
Result = PASS
deviceQuery で、正しくGPUを認識できているか確認します

対して、次のような表示の場合は、うまくCUDA on WSLのセットアップができていません。システム要件を満たしているか、CUDAドライバーが正しく入っているか、など再確認してみてください。

$ ./deviceQuery
./deviceQuery Starting...

 CUDA Device Query (Runtime API) version (CUDART static linking)

cudaGetDeviceCount returned 35
-> CUDA driver version is insufficient for CUDA runtime version
Result = FAIL

その他、前項ではbandwidthTest、simpleCUBLAS、simpleCUFFTもコンパイルしてますので、それも試してみてください。うまく動いていれば、次のような表示になります。

$ ./bandwidthTest
[CUDA Bandwidth Test] - Starting...
Running on...

 Device 0: NVIDIA GeForce GTX 960M
 Quick Mode

 Host to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(GB/s)
   32000000                     6.2

 Device to Host Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(GB/s)
   32000000                     6.4

 Device to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(GB/s)
   32000000                     70.0

Result = PASS

NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.
$ ./simpleCUBLAS
GPU Device 0: "Maxwell" with compute capability 5.0

simpleCUBLAS test running..
simpleCUBLAS test passed.
$ ./simpleCUFFT
[simpleCUFFT] is starting...
GPU Device 0: "Maxwell" with compute capability 5.0

Temporary buffer size 448 bytes
Transforming signal cufftExecC2C
Launching ComplexPointwiseMulAndScale<<< >>>
Transforming signal back cufftExecC2C

ここら辺まで確認できていれば、問題なくCUDA on WSLが使えると思います。セットアップお疲れ様でした。

おまけ

本当は、WSLgを使って「これだけでnbodyサンプルとかも表示できるよ」と説明したかったのですが、どうもうまく動きませんでした。(ウィンドウが一瞬だけ表示されて、下記のようなメッセージが出て落ちてしまう)

CUDA error at bodysystemcuda_impl.h:186 code=304(cudaErrorOperatingSystem) "cudaGraphicsGLRegisterBuffer(&m_pGRes[i], m_pbo[i], cudaGraphicsMapFlagsNone)"

どうも、CUDAの処理とOpenGLの処理が別のGPU(GeForceとCPU統合GPU)になっていると上記エラーが出てしまうようです。CPU統合GPUを無効にしたりすれば解決できそうなのですが、今回使ったパソコンでそのような設定をする方法がよく分かりませんでした。

CUDAを入れた意味が全くないですが、CPUで処理をするようにオプションをつけてnbodyを実行すると、激重なものの一応表示されます。なので、GeForceメインなパソコンであれば、ここまでの設定だけでnbodyやfluidGL、oceanFFTなども正しく実行できると思われます。

WSLgでnbody

参考サイト