cmdstanrパッケージでOpenCLを経由してGPUを使う方法についての試行錯誤の記録、その第三弾。こんどは、Windows上のWSL(Windows Subsystem for Linux)の上でLinuxを動かし、そこでcmdstanからGPUを使ってみようという試みである。
なんだか遠回りな話だが、一概にばかばかしいとはいえない。下のCase 21でわかるように、GPUを使わない場合、Windows上でcmdstanを使うより、おなじPCのWindows上のWSL上のLinux仮想マシン上でcmdstanを使ったほうが、計算速度が速かったりするのである。
目次
- Case 21-22の準備
- Case 21. Win10, WLS-Ubuntu22.04, R4.3.1, Rtools4.3, cmdstan2.32.2, OpenCLなし, 成功
- Case 22. Win10, WLS-Ubuntu22.04, R4.3.1, Rtools4.3, cmdstan2.32.2, OpenCL(NVIDIA CUDA11.4.4), 失敗
- Case 23-24の準備
- Case 23. Win11, WLS-Ubuntu22.04, R4.3.1, Rtools4.3, cmdstan2.33.1, OpenCLなし, 成功
- Case 24. Win11, WLS-Ubuntu22.04, R4.3.1, Rtools4.3, cmdstan2.33.1, OpenCL(NVIDIA CUDA12.2), 失敗
本件、ここ数日にわたってあれこれ試しすぎて頭が混乱してきたので、すべてを消して一からやりなおすことにする。
まずはWSL上で動くUbuntu仮想マシンの準備から。
- Windows 10 Home (22H2)
- WSLってなんだかいろいろあるらしいんだけど、ここではMicrosoft StoreからダウンロードしたWSL2を使ってます。
- 既存のdistroを削除。Windowsのコマンドラインから
wsl --unregistor
ついでにWindowsの「機能とアプリ」から、既存のdistroの項目をすべて削除。
- 念のため、wslそのものの更新を試みておく。
wsl --update wsl --version
WSLバージョンは 1.2.5.0 であった。
- どのdistroをいれようか考える。ちょっと楽しいですね。
wsl --list --online
- 無難にUtuntuをいれることにして…
wsl --install Ubuntu
ここでユーザ名とパスワードの設定を求められるはず。
- 今後のため、Windows Terminal上にUbuntu用の設定をつくっておく。これ、なんとなく自動で設定されるような気がしていたよ。私これまでどうしていたのだろうか?
- 名前: Ubuntu
- コマンドライン: wsl.exe -d Ubuntu
- 開始ディレクトリ: %USERPROFILE%
- アイコン: https://assets.ubuntu.com/v1/49a1a858-favicon-32×32.png
- 外観-テキスト-フォントサイズ: 11
- 外観-テキスト-見分けがつかないテキストの明るさを自動的に調整する: 常時
Windows TerminalでUbuntuのターミナル画面を開けることを確認。
- Ubuntuのリリースを確認する。Ubuntuのターミナルから
lsb_release -a
あいたたた、単にUbuntuと指定すると、Ubuntu 22.04.2 LTSとなるようだ。20.04がよかったんだけど… まあいいか…
- システムを更新しておく。Ubuntuのターミナルから
sudo apt update sudo apt upgrade
- R 4.3.1をインストール。CRANの指示に従い、
wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | sudo tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc sudo add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/" sudo apt install --no-install-recommends r-base
- RStudio Server 2023.06.1 Build 524 のインストール。posit様の指示に従い、
sudo apt-get install gdebi-core wget https://download2.rstudio.org/server/jammy/amd64/rstudio-server-2023.06.1-524-amd64.deb sudo gdebi rstudio-server-2023.06.1-524-amd64.deb
RStudio Serverがスタートしたようなので、Windows上のブラウザから localhost:8787 にアクセスし、ログインできることを確認。
こんどはOpenCLの設定。
- このPCにはGPUとしてNVIDIA GeForce GTX 660が載っています。ドライババージョンは474.44。
- まず、OpenCL実行環境について調べるためにclinfoをインストールしておく。Ubuntuのターミナルから
sudo apt install clinfo
さっそく
clinfo
と実行してみると、Number of platforms: 0
と表示される。まだOpenCLが設定できていないわけである。 - ここで肝心なのは、NVIDIAのドライバ類を一切インストールしないこと。単にCUDA ToolkitのWSL-Ubuntu版をインストールすればよいのである。
CUDA Toolkitのリリースノートを参照し、グラフィック・ドライバと整合する適切なバージョンを選び、CUDA Toolkitの配布ページを参照して、インストール用のコマンドを教えてもらう。
…というのは簡単だが、正直なところ、バージョンの選び方がわからない。リリースノートの説明が良く理解できないのだ。私の場合は11.7.1を選んでうまくいかず、すべてアンインストールして、11.4.4で再挑戦した。
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.4/local_installers/cuda-repo-wsl-ubuntu-11-4-local_11.4.4-1_amd64.deb sudo dpkg -i cuda-repo-wsl-ubuntu-11-4-local_11.4.4-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
最後の行は、liburcu6がないというエラーになった。以下を実行してから改めて実行した。
sudo add-apt-repository ppa:cloudhan/liburcu6 sudo apt update sudo apt install liburcu6
- 無事インストールは終わったが、
clinfo
は依然としてNumber of platforms: 0
と返してくる。こちらの投稿によれば、さらにOpenCL開発パッケージとランタイムが必要になる(とChatGPTが教えてくれたのだそうだ。ははは)。sudo apt-get install ocl-icd-opencl-dev sudo apt-get install pocl-opencl-icd
- 再度
clinfo
を動かしてみると… おお!なんか出てきた!Number of platforms 1 Platform Name Portable Computing Language Platform Vendor The pocl project Platform Version OpenCL 2.0 pocl 1.8 Linux, None+Asserts, RELOC, LLVM 11.1.0, SLEEF, DISTRO, POCL_DEBUG Platform Profile FULL_PROFILE Platform Extensions cl_khr_icd cl_pocl_content_size Platform Extensions function suffix POCL Platform Name Portable Computing Language Number of devices 1 Device Name pthread-Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz Device Vendor GenuineIntel Device Vendor ID 0x6c636f70 Device Version OpenCL 1.2 pocl HSTR: pthread-x86_64-pc-linux-gnu-ivybridge Driver Version 1.8 Device OpenCL C Version OpenCL C 1.2 pocl (後略)
しかし、Device NameのところにCPUが出てくるのが不安だなあ…
- NVIDEAのシステム管理ツール
nvidia-smi
の出力もおかしい。+-----------------------------------------------------------------------------+ | NVIDIA-SMI 470.199.01 Driver Version: 474.44 CUDA Version: 11.4 | |-------------------------------+----------------------+----------------------+ | 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 NVIDIA GeForce ... Off | 00000000:01:00.0 N/A | N/A | |ERR! 0C P8 N/A / N/A | 420MiB / 1536MiB | N/A Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
- いっぽう、
/usr/local/cuda/extras/demo_suite/deviceQuery
というツールによれば、GPUはちゃんと認識されている。./deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) Detected 1 CUDA Capable device(s) Device 0: "NVIDIA GeForce GTX 660" CUDA Driver Version / Runtime Version 11.4 / 11.4 CUDA Capability Major/Minor version number: 3.0 (後略)
よくわかんないけど、ちゃんとOpenCLに対応しているのだろうか。不安になってきた。
お待たせしました、cmdstanrの登場です。まずはOpenCLを使わないベンチマーク。
- cmdstanr 0.5.3開発版をインストール。
install.packages("remotes") remotes::install_github("stan-dev/cmdstanr")
- cmdstan2.32.2をインストール。
cmdstanr::install_cmdstan(cores = 4, overwrite = TRUE)
- コンパイル。前々回記事で作ったstantest.stanを使います。
mod <- cmdstan_model("./stantest.stan", force_recompile = TRUE)
- サンプリング。
n <- 250000 k <- 20 X <- matrix(rnorm(n * k), ncol = k) y <- rbinom(n, size = 1, prob = plogis(3 * X[,1] - 2 * X[,2] + 1)) mdata <- list(k = k, n = n, y = y, X = X) fit <- mod$sample(data = mdata, chains = 4, parallel_chains = 4, refresh = 100)
無事終了。所要時間は504秒であった。同じマシンのWindows上の所要時間が584秒だから、こっちのほうが少し早いわけだ。
いよいよOpenCLの登場。
- cmdstanr 0.5.3開発版をインストール。
- cmdstan2.32.2をインストール。
cmdstanr::install_cmdstan(cores = 4, overwrite = TRUE, cpp_options = list(STAN_OPENCL=TRUE))
- コンパイル。
mod <- cmdstan_model( "./stantest.stan", force_recompile = TRUE, cpp_options = list(stan_opencl = TRUE) )
- サンプリング。
n <- 250000 k <- 20 X <- matrix(rnorm(n * k), ncol = k) y <- rbinom(n, size = 1, prob = plogis(3 * X[,1] - 2 * X[,2] + 1)) mdata <- list(k = k, n = n, y = y, X = X) fit <- mod$sample(data = mdata, chains = 4, parallel_chains = 4, opencl_ids = c(0, 0), refresh = 100)
無事終了したが、所要時間はなんと970秒。それもそのはず、タスクマネージャを確認すると、GPUを全然使っていないのである。やっぱり、OpenCLが設定できていないようだ。
NVIDIAのCUDA on WSL User Guideによれば、公式にサポートしているGPUはPascal世代以降。その前のMaxwell世代のGPUはサポート外だがたぶん動く、とのこと。わがマシーンのGTX 660はさらにその前、Kepler世代ってやつだもんな。ダメか... がっくり。
[2023/10/11 追記] 新PCをお迎えしたので再挑戦。以下はその記録です。
まずはWSL2-Ubuntu環境の用意。
- Windows 11 Pro (22H2)
- Microsoft StoreからWSL2をインストール。
- 念のため、wslそのものの更新を試みたが(上述)、更新不要だった模様。WSLバージョンは 1.2.5.0。
- Utuntuのインストール。
wsl --install Ubuntu-22.04
ここでユーザ名とパスワードの設定を求められた。
- 今回は、Windows Terminal上にUbuntu用の設定が勝手に作られた。
- システムを更新しておく。上述。
- R 4.3.1をインストール。上述。
- RStudio Server 2023.09.0 Build 463 のインストール。posit様の指示に従い、
sudo apt-get install gdebi-core wget https://download2.rstudio.org/server/jammy/amd64/rstudio-server-2023.09.0-463-amd64.deb sudo gdebi rstudio-server-2023.09.0-463-amd64.deb
Windows上のブラウザから localhost:8787 にアクセスし、ログインできることを確認。
おつぎはOpenCLの設定。
- このPCにはGPUとしてNVIDIA GeForce GTX 4070が載っています(貧乏性の私としては結構張り込みました)。ドライババージョンは537.58。
- clinfoのインストール。上述。
- CUDA ToolkitのWSL-Ubuntu版をインストール。おそらく最新版で大丈夫だろうと踏んで、こちらで [Linux] - [x86_64] - [WSL-Ubuntu] - [2.0] - [dev(network)] を選んだところ、以下の神託がくだされた。
wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-keyring_1.1-1_all.deb sudo dpkg -i cuda-keyring_1.1-1_all.deb sudo apt-get update sudo apt-get -y install cuda
最後までエラーなしで実行できました。なお、後述する
nvidia-smi
の出力によれば、インストールされたのはCUDA 12.2らしい。 clinfo
は依然としてNumber of platforms: 0
と返してくる。- OpenCL開発パッケージとランタイムをインストール。
sudo apt-get install ocl-icd-opencl-dev sudo apt-get install pocl-opencl-icd
- 再度
clinfo
を動かしてみると...Number of platforms 1 Platform Name Portable Computing Language Platform Vendor The pocl project Platform Version OpenCL 2.0 pocl 1.8 Linux, None+Asserts, RELOC, LLVM 11.1.0, SLEEF, DISTRO, POCL_DEBUG Platform Profile FULL_PROFILE Platform Extensions cl_khr_icd cl_pocl_content_size Platform Extensions function suffix POCL Platform Name Portable Computing Language Number of devices 1 Device Name pthread-13th Gen Intel(R) Core(TM) i5-13400F Device Vendor GenuineIntel Device Vendor ID 0x6c636f70 Device Version OpenCL 1.2 pocl HSTR: pthread-x86_64-pc-linux-gnu-goldmont Driver Version 1.8 Device OpenCL C Version OpenCL C 1.2 pocl (後略)
今回も、Device NameのところにCPUが出てきている... 不安だ...
- NVIDEAのシステム管理ツール
nvidia-smi
の出力は以下のとおり。こちらはGPUが表示されている。+---------------------------------------------------------------------------------------+ | NVIDIA-SMI 535.112 Driver Version: 537.42 CUDA Version: 12.2 | |-----------------------------------------+----------------------+----------------------+ | 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 NVIDIA GeForce RTX 4070 On | 00000000:01:00.0 On | N/A | | 0% 52C P8 12W / 200W | 908MiB / 12282MiB | 2% Default | | | | N/A | +-----------------------------------------+----------------------+----------------------+ +---------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=======================================================================================| | 0 N/A N/A 26 G /Xwayland N/A | +---------------------------------------------------------------------------------------+
/usr/local/cuda/extras/demo_suite/deviceQuery
というツールによれば、GPUはちゃんと認識されている。/usr/local/cuda/extras/demo_suite/deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) Detected 1 CUDA Capable device(s) Device 0: "NVIDIA GeForce RTX 4070" CUDA Driver Version / Runtime Version 12.2 / 12.2 CUDA Capability Major/Minor version number: 8.9 (後略)
では、準備はできたということにして、いよいよテストです。
まずはOpenCLを使わないベンチマーク。
- cmdstanr 0.6.1をインストール。
install.packages("cmdstanr", repos = c("https://mc-stan.org/r-packages/", getOption ("repos")))
- cmdstan2.33.1をインストール。
cmdstanr::install_cmdstan(cores = 4, overwrite = TRUE)
- コンパイル。前々回記事で作ったstantest2.stanを使います。
mod <- cmdstan_model("./stantest.stan", force_recompile = TRUE)
- サンプリング。
n <- 250000 k <- 20 X <- matrix(rnorm(n * k), ncol = k) y <- rbinom(n, size = 1, prob = plogis(3 * X[,1] - 2 * X[,2] + 1)) mdata <- list(k = k, n = n, y = y, X = X) fit <- mod$sample(data = mdata, chains = 4, parallel_chains = 4, refresh = 100)
無事終了。所要時間は203秒であった。
いよいよOpenCLの登場。
- cmdstanr 0.6.1をインストール。
- cmdstan2.33.1をインストール。
cmdstanr::install_cmdstan(cores = 4, overwrite = TRUE, cpp_options = list(STAN_OPENCL=TRUE))
- コンパイル。
mod <- cmdstan_model( "./stantest2.stan", force_recompile = TRUE, cpp_options = list(stan_opencl = TRUE) )
- サンプリング。
n <- 250000 k <- 20 X <- matrix(rnorm(n * k), ncol = k) y <- rbinom(n, size = 1, prob = plogis(3 * X[,1] - 2 * X[,2] + 1)) mdata <- list(k = k, n = n, y = y, X = X) fit <- mod$sample(data = mdata, chains = 4, parallel_chains = 4, opencl_ids = c(0, 0), refresh = 100)
固唾をのんでタスクマネージャを見守ったが、期待に反し、GPUではなくCPUが猛烈に動き出した。無事終了したが、所要時間は400秒。
opencl_ids
の設定がいかんのかなと思い、試しにc(0,1)
,c(1,0)
,c(1,1)
を試したが、いずれもエラーになった。- ためしに
sudo apt-get purge ocl-icd-opencl-dev sudo apt-get purge pocl-opencl-icd
として再挑戦したが、事態は改善しないどころか、Stanのコンパイルがエラーとなった。
巷の情報をみるに、WSL2上でNVIDIAのGPUを使うことはできる、しかしOpenCLを経由して使えるわけではない... ということなのかもしれない。話が複雑すぎてよくわからないんだけど。
というわけで、「WSLの上のLinuxの上でcmdstanからGPUを使う」作戦はいまだ成功をみていない。がっくり。