Win11+WSL2+Dockerでのディープラーニング環境設定メモ

Win11およびWSL2(Ubuntu20.04)上にMiniconda3、Nvidia+Cuda環境を作成する

前提

  • NVIDIA RTX3070を使用
  • Win11にWSL2+Ubuntu20.04を構築
  • Dockerをインストール

Miniconda3 インストール (Win11, WSL2)


Win11のホスト、WSL2内の両方にPython3.8のMiniconda3をインストール

https://repo.anaconda.com/miniconda/Miniconda3-py38_4.12.0-Windows-x86_64.exe

> wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
> bash Miniconda3-latest-Linux-x86_64.sh

defaultsチャンネルを削除してconda-forgeをデフォルトにする

> conda config --add channels conda-forge
> conda config --remove channels defaults
> conda update --all

Win11のホスト側にNVIDIAドライバは2022-09時点での最新バージョンを入れる。

CUDAは11.3.1 Update 1を使用する。(Pytorch, Tensorflowで認識)

https://developer.nvidia.com/cuda-11-3-1-download-archive

cuDNNは、CUDAバージョンに合わせて8.4.1.50をインストール

https://developer.nvidia.com/rdp/cudnn-archive

コマンドプロンプトで確認

> nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2021 NVIDIA Corporation
Built on Mon_May__3_19:41:42_Pacific_Daylight_Time_2021
Cuda compilation tools, release 11.3, V11.3.109
Build cuda_11.3.r11.3/compiler.29920130_0

Pytorchインストール (Win11, WSL2)


Win11+Minoconda3環境にPytorchをインストール。GPUが利用可能か確認する。

torch.cuda.is_available()TrueならOK

> conda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch

> python

>>> import torch
>>> torch.cuda.is_available()
True

WSL2上でも、上記と同じ環境を構築して動作すること。
Win11だと最新のWSL2環境でもGPUが利用可能なので、同じ感覚で利用できるはず。

Tensorflow GPU版インストール (WSL2)


以下は、WSL2に対してTensorflowのGPU版をインストールして、WSL2内からGPUが認識できている確認

(Win11環境だと、tensorflow-gpuがない?)

> conda install tensorflow-gpu=2.8.1=cuda112py38h0bbbad9_0

> python
>>> from tensorflow.python.client import device_lib
>>> print(device_lib.list_local_devices())
:
incarnation: 6470249754415725170
physical_device_desc: "device: 0, name: NVIDIA GeForce RTX 3070, pci bus id: 0000:07:00.0, compute capability: 8.6"
xla_global_id: 416903419
]

とりあえずここまでで、Win11やWSL2上でGPU版が動作できる環境が作成できた。

が、このままだと、Dockerコンテナ内からはGPUが参照できてない。以下のコンテナを実行するとエラーになった。

> docker run --rm --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark
docker: Error response from daemon: could not select device driver "" with capabilities: [[gpu]].
ERRO[0000] error waiting for container: context canceled

WSL2 + Dockerコンテナ内からGPUを認識できるようにする。


どうやら、NVIDIA Container Toolkitが必要らしい(旧 nvidia-docker2 )

https://zenn.dev/holliy/articles/e1ac7f2f806c35

https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#setting-up-nvidia-container-toolkit

nvidia-container-toolkitのインストール

> distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
    && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
        sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
    && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
        sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
        sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
> sudo apt update
> sudo apt install -y nvidia-container-toolkit

重要なのは、インストール後にDockerデーモンを再起動する必要がある。

# Dockerデーモンの再起動
$ sudo service stop docker
$ sudo service start docker

再度、コンテナ内からGPUを認識するかチェック

> docker run --rm --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark
:
> Windowed mode
> Simulation data stored in video memory
> Single precision floating point simulation
> 1 Devices used for simulation
GPU Device 0: "Ampere" with compute capability 8.6

> Compute 8.6 CUDA device: [NVIDIA GeForce RTX 3070]
47104 bodies, total time for 10 iterations: 40.243 ms
= 551.345 billion interactions per second
= 11026.891 single-precision GFLOP/s at 20 flops per interaction

認識していたら、TensorflowのGPU版Pytorchのコンテナを取得してその中で確認する。

> docker run --gpus all -it --rm tensorflow/tensorflow:2.8.1-gpu bash

________                               _______________
___  __/__________________________________  ____/__  /________      __
__  /  _  _ \_  __ \_  ___/  __ \_  ___/_  /_   __  /_  __ \_ | /| / /
_  /   /  __/  / / /(__  )/ /_/ /  /   _  __/   _  / / /_/ /_ |/ |/ /
/_/    \___//_/ /_//____/ \____//_/    /_/      /_/  \____/____/|__/


> python
>>> from tensorflow.python.client import device_lib
>>> print(device_lib.list_local_devices())
:
incarnation: 6470249754415725170
physical_device_desc: "device: 0, name: NVIDIA GeForce RTX 3070, pci bus id: 0000:07:00.0, compute capability: 8.6"
xla_global_id: 416903419
]

ラストはDockerコンテナ版のPytorch

> docker pull pytorch/pytorch:1.10.0-cuda11.3-cudnn8-devel

> docker run -it --rm --gpus all pytorch/pytorch:1.10.0-cuda11.3-cudnn8-devel bash

> python
>>> import torch
>>> torch.cuda.is_available()
True
>>> torch.cuda.device_count()
1
>>> torch.cuda.current_device()
0
>>> torch.cuda.get_device_name()
'NVIDIA GeForce RTX 3070'
>>> torch.cuda.get_device_capability()
(8, 6)

Opencv


> conda install opencv=4.6.0=py38h373033e_4

> python
>>> import cv2

Miniconda3の環境エクスポート、インポート


https://qiita.com/ozaki_physics/items/13466d6d1954a0afeb3b

activate中の環境のモジュール一覧をエクスポートする

> conda activate xxx
> conda env export > xxx.yml

出力したファイルから環境を構築する

> conda env create -n zzz -f xxx.yml

上記をインストールした直後のWSL2向けパッケージ一覧

name: deep
channels:
  - pytorch
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=conda_forge
  - _openmp_mutex=4.5=2_kmp_llvm
  - abseil-cpp=20210324.2=h9c3ff4c_0
  - absl-py=1.2.0=pyhd8ed1ab_0
  - aiohttp=3.8.1=py38h0a891b7_1
  - aiosignal=1.2.0=pyhd8ed1ab_0
  - alsa-lib=1.2.6.1=h7f98852_0
  - aom=3.4.0=h27087fc_1
  - astunparse=1.6.3=pyhd8ed1ab_0
  - async-timeout=4.0.2=pyhd8ed1ab_0
  - attr=2.5.1=h166bdaf_1
  - attrs=22.1.0=pyh71513ae_1
  - blas=2.116=mkl
  - blas-devel=3.9.0=16_linux64_mkl
  - blinker=1.4=py_1
  - brotlipy=0.7.0=py38h0a891b7_1004
  - bzip2=1.0.8=h7f98852_4
  - c-ares=1.18.1=h7f98852_0
  - ca-certificates=2022.6.15=ha878542_0
  - cached-property=1.5.2=hd8ed1ab_1
  - cached_property=1.5.2=pyha770c72_1
  - cachetools=5.2.0=pyhd8ed1ab_0
  - cairo=1.16.0=ha61ee94_1013
  - certifi=2022.6.15=pyhd8ed1ab_1
  - cffi=1.15.1=py38h4a40e3a_0
  - charset-normalizer=2.1.1=pyhd8ed1ab_0
  - click=8.1.3=py38h578d9bd_0
  - cryptography=37.0.4=py38h2b5fc30_0
  - cudatoolkit=11.3.1=h9edb442_10
  - cudnn=8.4.1.50=hed8a83a_0
  - dbus=1.13.6=h5008d03_3
  - expat=2.4.8=h27087fc_0
  - ffmpeg=4.4.2=gpl_hfe78399_107
  - fftw=3.3.10=nompi_hf0379b8_105
  - font-ttf-dejavu-sans-mono=2.37=hab24e00_0
  - font-ttf-inconsolata=3.000=h77eed37_0
  - font-ttf-source-code-pro=2.038=h77eed37_0
  - font-ttf-ubuntu=0.83=hab24e00_0
  - fontconfig=2.14.0=h8e229c2_0
  - fonts-conda-ecosystem=1=0
  - fonts-conda-forge=1=0
  - freeglut=3.2.2=h9c3ff4c_1
  - freetype=2.12.1=hca18f0e_0
  - frozenlist=1.3.1=py38h0a891b7_0
  - gast=0.5.3=pyhd8ed1ab_0
  - gettext=0.19.8.1=h73d1719_1008
  - giflib=5.2.1=h36c2ea0_2
  - glib=2.72.1=h6239696_0
  - glib-tools=2.72.1=h6239696_0
  - gmp=6.2.1=h58526e2_0
  - gnutls=3.7.7=hf3e180e_0
  - google-auth=2.11.0=pyh6c4a22f_0
  - google-auth-oauthlib=0.4.6=pyhd8ed1ab_0
  - google-pasta=0.2.0=pyh8c360ce_0
  - graphite2=1.3.13=h58526e2_1001
  - grpc-cpp=1.45.2=h9d3bbbb_5
  - grpcio=1.45.0=py38ha0cdfde_0
  - gst-plugins-base=1.20.3=hf6a322e_0
  - gstreamer=1.20.3=hd4edc92_1
  - h5py=3.7.0=nompi_py38h045baee_101
  - harfbuzz=5.1.0=hf9f4e7c_0
  - hdf5=1.12.2=nompi_h2386368_100
  - icu=70.1=h27087fc_0
  - idna=3.3=pyhd8ed1ab_0
  - importlib-metadata=4.11.4=py38h578d9bd_0
  - jack=1.9.18=h8c3723f_1002
  - jasper=2.0.33=ha77e612_0
  - jpeg=9e=h166bdaf_2
  - keras=2.8.0=pyhd8ed1ab_0
  - keras-preprocessing=1.1.2=pyhd8ed1ab_0
  - keyutils=1.6.1=h166bdaf_0
  - krb5=1.19.3=h3790be6_0
  - lame=3.100=h7f98852_1001
  - lcms2=2.12=hddcbb42_0
  - ld_impl_linux-64=2.36.1=hea4e1c9_2
  - lerc=4.0.0=h27087fc_0
  - libblas=3.9.0=16_linux64_mkl
  - libcap=2.64=ha37c62d_0
  - libcblas=3.9.0=16_linux64_mkl
  - libclang=14.0.6=default_h2e3cab8_0
  - libclang13=14.0.6=default_h3a83d3e_0
  - libcups=2.3.3=h3e49a29_2
  - libcurl=7.83.1=h7bff187_0
  - libdb=6.2.32=h9c3ff4c_0
  - libdeflate=1.13=h166bdaf_0
  - libdrm=2.4.113=h166bdaf_0
  - libedit=3.1.20191231=he28a2e2_2
  - libev=4.33=h516909a_1
  - libevent=2.1.10=h9b69904_4
  - libffi=3.4.2=h7f98852_5
  - libflac=1.3.4=h27087fc_0
  - libgcc-ng=12.1.0=h8d9b700_16
  - libgfortran-ng=12.1.0=h69a702a_16
  - libgfortran5=12.1.0=hdcd56e2_16
  - libglib=2.72.1=h2d90d5f_0
  - libglu=9.0.0=he1b5a44_1001
  - libgomp=12.1.0=h8d9b700_16
  - libiconv=1.16=h516909a_0
  - libidn2=2.3.3=h166bdaf_0
  - liblapack=3.9.0=16_linux64_mkl
  - liblapacke=3.9.0=16_linux64_mkl
  - libllvm14=14.0.6=he0ac6c6_0
  - libnghttp2=1.47.0=hdcd2b5c_1
  - libnsl=2.0.0=h7f98852_0
  - libogg=1.3.4=h7f98852_1
  - libopencv=4.6.0=py38h3504efa_3
  - libopus=1.3.1=h7f98852_1
  - libpciaccess=0.16=h516909a_0
  - libpng=1.6.37=h753d276_4
  - libpq=14.5=hd77ab85_0
  - libprotobuf=3.20.1=h6239696_1
  - libsndfile=1.0.31=h9c3ff4c_1
  - libsqlite=3.39.2=h753d276_1
  - libssh2=1.10.0=haa6b8db_3
  - libstdcxx-ng=12.1.0=ha89aaad_16
  - libtasn1=4.19.0=h166bdaf_0
  - libtiff=4.4.0=h0e0dad5_3
  - libtool=2.4.6=h9c3ff4c_1008
  - libudev1=249=h166bdaf_4
  - libunistring=0.9.10=h7f98852_0
  - libuuid=2.32.1=h7f98852_1000
  - libuv=1.44.2=h166bdaf_0
  - libva=2.15.0=h166bdaf_0
  - libvorbis=1.3.7=h9c3ff4c_0
  - libvpx=1.11.0=h9c3ff4c_3
  - libwebp-base=1.2.4=h166bdaf_0
  - libxcb=1.13=h7f98852_1004
  - libxkbcommon=1.0.3=he3ba5ed_0
  - libxml2=2.9.14=h22db469_4
  - libzlib=1.2.12=h166bdaf_2
  - llvm-openmp=14.0.4=he0ac6c6_0
  - markdown=3.4.1=pyhd8ed1ab_0
  - markupsafe=2.1.1=py38h0a891b7_1
  - mkl=2022.1.0=h84fe81f_915
  - mkl-devel=2022.1.0=ha770c72_916
  - mkl-include=2022.1.0=h84fe81f_915
  - multidict=6.0.2=py38h0a891b7_1
  - mysql-common=8.0.30=haf5c9bc_1
  - mysql-libs=8.0.30=h28c427c_1
  - nccl=2.14.3.1=h0800d71_0
  - ncurses=6.3=h27087fc_1
  - nettle=3.8.1=hc379101_1
  - nspr=4.32=h9c3ff4c_1
  - nss=3.78=h2350873_0
  - numpy=1.23.2=py38h3a7f9d9_0
  - oauthlib=3.2.0=pyhd8ed1ab_0
  - opencv=4.6.0=py38h578d9bd_3
  - openh264=2.3.0=h27087fc_0
  - openjpeg=2.5.0=h7d73246_1
  - openssl=1.1.1q=h166bdaf_0
  - opt_einsum=3.3.0=pyhd8ed1ab_1
  - p11-kit=0.24.1=hc5aa10d_0
  - pcre=8.45=h9c3ff4c_0
  - pillow=9.2.0=py38ha3b2c9c_2
  - pip=22.2.2=pyhd8ed1ab_0
  - pixman=0.40.0=h36c2ea0_0
  - portaudio=19.6.0=h57a0ea0_5
  - protobuf=3.20.1=py38hfa26641_0
  - pthread-stubs=0.4=h36c2ea0_1001
  - pulseaudio=14.0=h7f54b18_8
  - py-opencv=4.6.0=py38h7f3c49e_3
  - pyasn1=0.4.8=py_0
  - pyasn1-modules=0.2.7=py_0
  - pycparser=2.21=pyhd8ed1ab_0
  - pyjwt=2.4.0=pyhd8ed1ab_0
  - pyopenssl=22.0.0=pyhd8ed1ab_0
  - pysocks=1.7.1=pyha2e5f31_6
  - python=3.8.13=h582c2e5_0_cpython
  - python-flatbuffers=2.0=pyhd8ed1ab_0
  - python_abi=3.8=2_cp38
  - pytorch=1.10.2=py3.8_cuda11.3_cudnn8.2.0_0
  - pytorch-mutex=1.0=cuda
  - pyu2f=0.1.5=pyhd8ed1ab_0
  - qt-main=5.15.4=ha5833f6_2
  - re2=2022.06.01=h27087fc_0
  - readline=8.1.2=h0f457ee_0
  - requests=2.28.1=pyhd8ed1ab_1
  - requests-oauthlib=1.3.1=pyhd8ed1ab_0
  - rsa=4.9=pyhd8ed1ab_0
  - scipy=1.9.1=py38hea3f02b_0
  - setuptools=65.3.0=pyhd8ed1ab_1
  - six=1.16.0=pyh6c4a22f_0
  - snappy=1.1.9=hbd366e4_1
  - sqlite=3.39.2=h4ff8645_1
  - svt-av1=1.2.1=h27087fc_0
  - tbb=2021.5.0=h924138e_1
  - tensorboard=2.8.0=pyhd8ed1ab_1
  - tensorboard-data-server=0.6.0=py38h2b5fc30_2
  - tensorboard-plugin-wit=1.8.1=pyhd8ed1ab_0
  - tensorflow=2.8.1=cuda112py38hded6998_0
  - tensorflow-base=2.8.1=cuda112py38had2df90_0
  - tensorflow-estimator=2.8.1=cuda112py38hf5dcc89_0
  - tensorflow-gpu=2.8.1=cuda112py38h0bbbad9_0
  - termcolor=1.1.0=pyhd8ed1ab_3
  - tk=8.6.12=h27826a3_0
  - torchaudio=0.10.2=py38_cu113
  - torchvision=0.11.3=py38_cu113
  - typing-extensions=4.3.0=hd8ed1ab_0
  - typing_extensions=4.3.0=pyha770c72_0
  - urllib3=1.26.11=pyhd8ed1ab_0
  - werkzeug=2.2.2=pyhd8ed1ab_0
  - wheel=0.37.1=pyhd8ed1ab_0
  - wrapt=1.14.1=py38h0a891b7_0
  - x264=1!164.3095=h166bdaf_2
  - x265=3.5=h924138e_3
  - xcb-util=0.4.0=h166bdaf_0
  - xcb-util-image=0.4.0=h166bdaf_0
  - xcb-util-keysyms=0.4.0=h166bdaf_0
  - xcb-util-renderutil=0.3.9=h166bdaf_0
  - xcb-util-wm=0.4.1=h166bdaf_0
  - xorg-fixesproto=5.0=h7f98852_1002
  - xorg-inputproto=2.3.2=h7f98852_1002
  - xorg-kbproto=1.0.7=h7f98852_1002
  - xorg-libice=1.0.10=h7f98852_0
  - xorg-libsm=1.2.3=hd9c2040_1000
  - xorg-libx11=1.7.2=h7f98852_0
  - xorg-libxau=1.0.9=h7f98852_0
  - xorg-libxdmcp=1.1.3=h7f98852_0
  - xorg-libxext=1.3.4=h7f98852_1
  - xorg-libxfixes=5.0.3=h7f98852_1004
  - xorg-libxi=1.7.10=h7f98852_0
  - xorg-libxrender=0.9.10=h7f98852_1003
  - xorg-renderproto=0.11.1=h7f98852_1002
  - xorg-xextproto=7.3.0=h7f98852_1002
  - xorg-xproto=7.0.31=h7f98852_1007
  - xz=5.2.6=h166bdaf_0
  - yarl=1.7.2=py38h0a891b7_2
  - zipp=3.8.1=pyhd8ed1ab_0
  - zlib=1.2.12=h166bdaf_2
  - zstd=1.5.2=h6239696_4
prefix: /home/chihiro/miniconda3/envs/deep
-->