while(1) work();
article thumbnail
반응형

2020년에 Windows10 기준으로 타 사이트에 작성한 글을 가져왔습니다. WSL 업데이트로 인해 지금도 이렇게 동작하는지 알 수 없으니 참고용으로만 읽어주세요.

 

서론

Windows의 Docker 환경에서는 GPU CUDA를 사용할 수 없다. 좀 더 정확히 말하면 Nvidia-docker가 Windows를 지원하지 않는다. 따라서 CUDA를 사용하기 위해서는 Linux 환경이 필요한데, 현실적으로 개발 환경을 Linux로 구축하기에는 다소 어려움이 따른다.

하지만 다행히, Microsoft의 WSL(Windows Subsystem for Linux)이라는 기술을 사용할 수 있다.

본 글에서는 WSL(WSL2)을 사용하여 가상 리눅스 시스템을 구축하고 리눅스에 Docker를 설치하여 Docker 내부에서 CUDA를 사용할 수 있도록 하는 방법을 다룬다.

WSL2 활성화

WSL을 사용하기 위해서는 먼저 WSL 기능을 활성화 시켜주어야 한다.

관리자 권한이 있는 명령 프롬포트에서 아래 명령어를 실행시켜 주자.

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

더불어, WSL의 버전을 2로 올려주는 작업이 필요하다.

https://docs.microsoft.com/ko-kr/windows/wsl/wsl2-kernel 에서 WSL2 커널을 다운로드받아 설치한 뒤 아래 명령어를 실행한다.

wsl --set-default-version 2

WSL에 Ubnutu 설치

Microsoft Store에서 WSL을 검색한뒤 Ubuntu를 설치해 준다.

설치 후 Ubuntu를 실행하게 되면 Ubuntu 설치 작업이 마무리 된다.

만약 추가적인 계정을 생성하지 않고 root 계정만 사용하고 싶은 경우, Ubuntu 창에서 New user name을 입력하라는 단계에서 커멘드 창을 종료하면 된다.

설치가 완료되면 명령프롬포트에서 아래 명령어를 실행해 설치가 되었음을 확인할 수 있다.

> wsl -l
Linux용 Windows 하위 시스템 배포:
Ubuntu-20.04(기본값)

아래 명령어를 통해 Ubuntu 시스템에 접속할 수 있다.

> wsl -d Ubuntu-20.04

또는, Ubuntu를 기본 wsl 시스템으로 지정할수도 있다.

> wsl --set-default Ubnutu-20.04
> wsl

Ubuntu 시스템에서 나오기 위해서는 exit 명령어를 입력하면 되고, (모든)시스템을 강제종료할때는 아래 명령어를 이용한다.

> wsl --shutdown

이제 Ubuntu 시스템에 접속해서 커널 버전을 확인하자.

> wsl
root@HOST:/root# uname -r
4.19.104-microsoft-standard

커널 버전이 4.19.121 이하인 경우 안타깝게도, WSL에서 GPU를 사용할 수 없다. (자세한 내용은 https://docs.microsoft.com/ko-kr/windows/wsl/kernel-release-notes)

따라서, 커널 버전을 올려주는 작업이 필요하지만, 4.19.121커널은 현재 Windows Insider Preview(Windows 참가자 프로그램)에서만 사용할 수 있다.

Windows의 설정에서 Windows Insider Preview를 활성화 시킨 뒤 Windows 업데이트를 수행하고 아래 명령어를 입력한다.

> wsl --update
> wsl --shutdown
> wsl
root@HOST:/root# uname -r
4.19.121-microsoft-standard

Docker 설치

Windows 시스템에 Docker가 설치되어 있는경우 Docker의 설정을 통해 기본적으로 WSL 내부에서 Docker를 사용할 수 있다.

하지만, 서론에서 밝힌 바와 같이 Windows의 Docker는 GPU 가속을 지원하지 않기 때문에 해당 기능을 반드시 OFF 하고 WSL 내부에서 Docker를 새로 설치해 주어야 한다.

root@HOST:/root# apt-get install docker.io

또한 nvidia-docker를 설치해주자.

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

apt update
apt-get install nvidia-docker2
usermod -aG docker ____권한 줄 유저____

마지막으로 Windows에 NVIDIA Driver for CUDA on WSL 을 설치해주면 기본 작업이 끝난다.

https://developer.nvidia.com/cuda/wsl/download 에서 적절한 드라이버를 다운로드 후 설치해주고, 컴퓨터를 재부팅해주자.

Python 컨테이너

이제, Docker에서 python 컨테이너를 생성할 때 몇 가지 옵션만 주면 CUDA를 정상적으로 이용할 수 있다.

docker run --runtime=nvidia -e NVIDIA_DRIVER_CAPABILITIES=compute,utility -e NVIDIA_VISIBLE_DEVICES=all -it python /bin/bash

--runtime=nvidia 대신 --gpus=all을 사용해도 무방하나, nvidia-docker2부터는 --runtime=nvidia 를 권장한다.

-e는 docker 컨테이너에 환경변수를 주입하는 옵션으로, NVIDIA_DRIVER_CAPABILITIES와 NVIDIA_VISIBLE_DEVICES라는 환경변수를 만들어준다.

컨테이너 내부에서 pytorch를 설치하고(pip install torch torchvision) 아래 코드를 실행시켜보면 잘 동작함을 알 수 있다.

import torch

dtype = torch.float
#device = torch.device("cpu")
device = torch.device("cuda:0") # Uncomment this to run on GPU

# N is batch size; D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 64, 1000, 100, 10

# Create random input and output data
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)

# Randomly initialize weights
w1 = torch.randn(D_in, H, device=device, dtype=dtype)
w2 = torch.randn(H, D_out, device=device, dtype=dtype)

learning_rate = 1e-6
for t in range(500):
    # Forward pass: compute predicted y
    h = x.mm(w1)
    h_relu = h.clamp(min=0)
    y_pred = h_relu.mm(w2)

    # Compute and print loss
    loss = (y_pred - y).pow(2).sum().item()
    if t % 100 == 99:
        print(t, loss)

    # Backprop to compute gradients of w1 and w2 with respect to loss
    grad_y_pred = 2.0 * (y_pred - y)
    grad_w2 = h_relu.t().mm(grad_y_pred)
    grad_h_relu = grad_y_pred.mm(w2.t())
    grad_h = grad_h_relu.clone()
    grad_h[h < 0] = 0
    grad_w1 = x.t().mm(grad_h)

    # Update weights using gradient descent
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2

Pytorch 이미지 만들기

매번 Python 컨테이너를 생성해 Pytorch를 설치하는 작업은 굉장히 시간이 오래 걸리고 번거로운 작업이므로 아래와같이 Pytorch 이미지를 만들어 두고 사용할 수 있다.

Dockerfile에 아래 내용을 입력하자.

FROM python:latest

RUN pip install torch torchvision

ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
ENV NVIDIA_VISIBLE_DEVICES all

WORKDIR /root

ENTRYPOINT ["/bin/bash"]

그 다음 아래 명령어를 입력하면 Docker image가 생성된다.

root@HOST:/root# docker build -t mytorch .
root@HOST:/root# docker images

docker 컨테이너를 쉽게 생성하기 위해 /usr/bin/mytorch에 아래 내용을 입력한다.

docker run --runtime=nvidia -it -v ${PWD}:/root hotorch

그 다음 chmod 777 /usr/bin/mytorch 로 권한을 준 뒤 아래 명령어를 입력하면, 현재 폴더를 컨테이너의 /root로 마운트 시킨다.

root@HOST:/home/workspace# mytorch
반응형
profile

while(1) work();

@유호건

❤️댓글은 언제나 힘이 됩니다❤️ 궁금한 점이나 잘못된 내용이 있다면 댓글로 남겨주세요.

검색 태그