Windows에서 WSL2로 CUDA 를 실행해 보았다!

Microsoft WSL2 (Widdowns Subsystem Linux)

마이크로 소프트가 WSL2 를 발표 (https://devblogs.microsoft.com/commandline/announcing-wsl-2)해서 윈도우즈에서 리눅스 어플리케시션을 좀 더 좋게 사용할 수 있습니다.

윈도우즈에서 리눅스를 사용하려면 VMWare 나 VirtualBox같은 가상화 소프트웨어를 사용했습니다. 그래서 여러가지로 불편했었는데, WSL을 발표하면서 윈도우즈에서 가상 머신(VM)을 사용하지만, 파워 쉘에서 CLI 명령어로 사용할 수 있어서 좋았습니다. 하지만 Docker 라든가, Nvidia GPU를 사용할 수 없었죠.

WSL2 (Windows Subsystem Linux version 2)

마이크로 소프트에서 WSL2로 업데이트하면서 Linux 커널을 VM에 기반으로 실행하지만 시스템 콜 호환성을 100 % 로 바뀌었습니다. 그래서 WSL2 에서는 Nvidia CUDA를 사용할 수 있지 않을까 싶었지요.

2020 년 5 월의 BUILD 컨퍼런스에서 발표 (https://devblogs.microsoft.com/commandline/the-windows-subsystem-for-linux-build-2020-summary/) 한 WSL2 가 드디어 윈도우즈에서 CUDA를 사용할 수 있다고 합니다.

환경 구축

마이크로 소프트와 엔비디아의 양사 모두 문서가 나누어져 있어서 마이크로 소프트에서는 Services for UNIX (SFU) / Subsystem for UNIX-based Applications (SUA )를 참조하면서 엔비디아의 GPU를 써 보는 삽질을 시작했습니다.

자, 그럼 빨리 환경을 만들어야죠.

Nvidia 문서

Nvidia 문서[CUDA on WSL User Guide (https://docs.nvidia.com/cuda/wsl-user-guide/index.html#getting-started)를 참조해 가면서 삽질을 합니다.

Windows 10 Preview Build 20150 (이상) 설치

Windows 10 Insider Preview Build (20150 이상)을 설치합니다. Windows 10 Insider Preview Build

윈도우즈 Preview를 설치하기 위해서는 Windows Insider Preview의 Dev Channel에 참여를 신청하고 나면 설치가 활성화되어 설치할 수 있습니다.

다운로드 및 설치는 아주 오랜 시간이 걸립니다.

설치가 끝나면 파워쉘을 열고 명령 프롬프트에서 ver 명령을 실행해서 20150 (이상)인지 있는지 확인합니다.

C : \ WINDOWS \ system32> ver

Microsoft Windows [Version 10.0.20150.1000]

NVIDIA Drivers for CUDA on WSL 설치

NVIDIA Drivers for CUDA on WSL 설치를 참조하면서 진행합니다.

호스트 측 Windows의 준비되었으니 다음으로 NVIDIA 드라이버를 설치합니다.

이 드라이버는 WSL2 Linux 커널이 아닌 호스트 즉 윈도우에 설치합니다.

CUDA on Windows Subsystem for Linux (WSL) - Public Preview 페이지에서 Get CUDA Driver를 따라 드라이버 다운로드 페이지 이동하여 GeForce Driver 또는 Quadro Driver 중 하나를 자신의 환경에 맞게 다운로드합니다.

여기서 "NVIDIA Developer Program Membership Required"라고 표시되면 계정을 만들고 로그인 "Login"하세요.

설치 작업 자체는 Windows에 NVIDIA 드라이버를 설치 평소 절차와 다르지 않습니다. 자세한 내용은 생략합니다. 저는 모든 기본 옵션에서 다음, 다음으로 이동했습니다.

설치 완료 후 윈도우즈를 다시 시작해야합니다.

WSL2 설치

"가상 머신 플랫폼 '활성화

WSL2을 사용하기 위해서는 "가상 머신 플랫폼 '라는 Windows 기능이 필요합니다. 이것은 "Windows 기능 활성화 또는 비활성화"화면에서 할 수도 있지만, 쉽게 하려면 관리자 권한으로 실행하고 명령 프롬프트에서 다음 명령을 실행하면 쉽습니다.

※ 명령 프롬프트를 관리자 권한으로 실행하려면 Win + R에서 "파일 이름을 입력 한 다음 '에cmd를 입력 한 다음 CTRL + SHIFT + ENTER 버튼을 누르세요.

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

이 후 다음 명령을 실행하여 Linux 배포판이 WSL2에서 실행되도록합니다.

wsl --set-default-version 2

Linux 배포판 설치

Windows 10 Microsoft Store 앱에서 원하는 WSL 용 Linux 배포판을 설치합니다. 나는 Ubuntu-18.04에 했습니다.

컨테이너 실행 환경 꾸미기

CUDA on WSL2를 기다리고 있던 것은, NGC 컨테이너 이미지를 Windows에서 쉽게 실행하고 싶어셔 였습니다. 물론 Backend.AI도 실행하면 더 좋구요. WSL2에 Docker와 NVIDIA Container Toolkit을 설치합니다.

Docker 설치

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

이 때,

WSL DETECTED : We recommend using Docker Desktop for Windows.

말하지되지만 무시합니다.

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

여기까지 도커를 실행할 수 있도록 환경 구축이 끝났습니다.

또한 여기에서 설치 한 NVIDIA Container Toolkit은 일단 NVIDIA Docker 있던 것으로, 컨테이너 내에서 GPU를 활용하는 데 필요한 모듈입니다.

NGC 컨테이너 이미지를 실행해 보자!

환경이 완성했으니, NGC 컨테이너 이미지를 시도해 보죠. WSL2의 Ubuntu를 시작하고 다음 명령을 실행합니다.

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

컨테이너가 시작되면 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 = 160 \
  --precision = fp16

※ 덧붙여 WSL은 표준 콘솔 이외에도 다양한 소프트웨어에 액세스 할 수 있지만, 저는 [MobaXterm (https://mobaxterm.mobatek.net/)을 추천합니다. WSL에 대응하고있을뿐만 아니라 X 서버가 내장되어 편리합니다. 원격 접속도 이것 하나로 OK구요.

"Linux"와 다른 점

앞의 예제처럼 NGC 컨테이너 이미지를 움직이는 것만한다면 그다지 위화감없이 다른 Linux 시스템에 로그인하여 이동하는 것과 구별이 없을 정도입니다. 하지만 일반적인 Linux과 다른 이상한 점도 몇 가지 있습니다.

예를 들어,

lscpi해도 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 : can not access '/ dev / nvidia *': No such file or directory
# ls -l / proc / driver / nvidia
ls : can not access '/ proc / driver / nvidia': No such file or directory

이렇게, WSL2의 Linux는 PCI 장치로 GPU는 직접 보이지 않습니다.

NVIDIA 드라이버는 Windows에서만 설치한 것에서도 알 수 있듯이 GPU는 Windows 장치로 관리되고 있으며, WSL2의 Linux에서 그것을 "/dev/dxg"라는 장치를 통해 구현합니다. 이 /dev/dxg 가 반 가상화 장치입니다. 호스트 Windows와 WSL의 경량 VM으로 VMBus라는 가상 버스로 연결해서, Linux 측에서 /dev/dxg의 작업을 dxgkrnl 라는 반 가상화 드라이버와 VMBus를 통해 호스트의 GPU에 전달합니다.

근데 리눅스가 사용하는 반 가상화 장치(VMBus)는 윈도우즈의 하이퍼 바이저인 Hyper-V가 처음부터 가지고있는 것으로, 일반적으로 디스크 및 NIC 같은 장치를 완벽하게 에뮬레이션하는 것이 아니라 가상 환경에 최적화된 반 가상화 장치로 구현하기 위해 사용된 것입니다. 즉, Windows GPU를 WSL 측에서 사용하기 위해 사용하는 것이죠.

※ 여기서 등장한 Linux 커널의 dxgkrnl은 기존 기존 Windows DirectX 그래픽 커널과 같은 명칭이 있지만, 새로운 Linux에 구현 된 것이라고합니다.

소스 코드는 여기 : [WSL2-Linux-Kernel / drivers / gpu / dxgkrnl ](https://github.com/microsoft/WSL2-Linux-Kernel/tree/linux-msft-wsl-4.19.y/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 does not share anything else in common with its similarly named Windows counterpart.

출처 : DirectX is coming to the Windows Subsystem for Linux (https://devblogs.microsoft.com/directx/directx-heart-linux/)

제한 사항 (https://docs.nvidia.com/cuda/wsl-user-guide/index.html#known-limitations)

실제로 사용할 수 있게된 CUDA on WSL2이지만, 여전히 다음의 것들이 부족합니다.

  • Windows Insider Preview의 Dev Channel (Fast Ring)에서 제공
  • NVIDIA Driver도 프리뷰

이런 개발 프리뷰 단계이므로 아직 구현되지 않은 부분이 있습니다. 사용자 설명서의 제한 사항에서 일부 발췌하여 보면,

  • 성능에 관해서는 충분히 조정되지 않음
    • 사실 앞에서 예시 한 resnet.py도 Linux보다 약간 성능이 떨어질 수 있습니다
  • NVIDIA Management Library (NVML) API는 구현되지 않음
  • NVIDIA Container Toolkit에서는 docker run시 --gpus all만을 지원
  • 다중 GPU가있는 경우 일부에 한정하여 컨테이너에 사용 할 수 없습니다.

등이 있습니다.

그리고 NVML가 구현되지 않아서 nvidia-smi 같은 친숙한 명령도 사용할 수 없습니다. 부족한데로 파워쉡에서 nvidia-smi 를 윈도우에서 실행함으로 해서 GPU에 대하여 어느 정도의 정보를 얻을 수 있습니다.

정리

  • Windows 10의 WSL2에서 마침내 CUDA를 사용할 수 있다!
  • NGC의 TensorFlow 컨테이너 이미지 등도 실행된다!
  • Windows Insider Preview와 NVIDIA Developer Program에 등록!
  • 성능 및 관리 측면에서 일부 제한 사항도!

즐거운 AI/ML하십시오!