학교에서 병렬 컴퓨팅 수업을 수강하게 되면서 어쩔 수 없이 CUDA 프로그래밍을 하게 되었다. 맥북 유저인 나는 Colab 을 사용해 %%writefile 과 같은 방식으로 실습을 하거나 GPU 서버 임대를 하는 방식이 있지만 개발 경험과 비용을 다 놓치고 싶지 않기에 본가에 있는 GTX 950 그래픽카드가 있는 데스크톱을 서버로 만들기로 결심했다. 전기세는 부모님이…

구성은 단순하다.

  • Windows 데스크톱 + WSL2 Ubuntu 위에서 CUDA 개발
  • Tailscale 로 어디서든 SSH
  • PC 재부팅만 하면 다시 붙을 정도로 복구를 단순화

전체 구조

맥북에서는 코드를 쓰고, 실제 컴파일·실행은 본가 서버의 WSL 안에서 한다. 인터넷에 서버를 직접 열어두지 않고 Tailscale 사설망으로만 붙는다.

[맥북] --Tailscale--> [본가 Windows]
                           └─ WSL2 (Ubuntu)
                                ├─ Tailscale SSH
                                └─ CUDA Toolkit (nvcc)
                                     └─ GPU (Windows 드라이버 passthrough)

WSL2 + CUDA

1. Windows 쪽 준비

  1. WSL2 + Ubuntu 설치
  2. NVIDIA Windows 드라이버 최신본 설치 (Game Ready / Studio 아무거나)
  3. PowerShell 에서 wsl --shutdown 후 WSL 재시작

WSL 안에서 드라이버 설치 전에 먼저 확인한다.

nvidia-smi

여기서 GPU 가 보이면 Windows → WSL passthrough 는 일단 살아 있는 것이다. 안 보이면 Toolkit 을 아무리 깔아도 소용없다. 드라이버 재설치와 wsl --shutdown 부터 다시 보자.

2. cuda 설치 전에 버전 확인

Toolkit 을 무작정 최신으로 깔면 오류가 발생할 수 있으니 GPU의 Compute Capability 같은 것을 확인해야 한다.

GPU 가 지원하는 CUDA / Compute Capability

GPU 마다 Compute Capability(CC) 가 있고, Toolkit 버전이 올라가면 오래된 CC 지원이 끊긴다.

nvidia-smi --query-gpu=name,compute_cap --format=csv

예를 들어 GTX 950 이면 대략 5.2(Maxwell) 가 나온다. 모델 ↔ CC 표는 CUDA GPU Compute Capability 에서 확인하고, 그 CC 를 아직 지원하는 Toolkit 범위는 각 CUDA 릴리즈 노트 / 지원 매트릭스 에서 본다.

WSL(Ubuntu) + Windows 드라이버가 허용하는 최대 CUDA

WSL 안의 CUDA 런타임은 결국 Windows 에 깔린 NVIDIA 드라이버를 쓴다. 그래서 드라이버가 허용하는 최대 CUDA 버전을 넘기면 안 된다.

nvidia-smi

출력 오른쪽 위 CUDA Version: X.Y 가 그 상한이다. 여기에 12.6 이 찍혀 있으면 Toolkit 도 12.6 이하로 맞춰야 한다. (nvidia-smi 의 CUDA Version 은 “지금 설치된 Toolkit 버전”이 아니라 이 드라이버가 지원하는 최대 CUDA 다.)

추가로 WSL-Ubuntu 용 패키지가 실제로 뭐가 있는지도 본다. keyring 추가 후:

apt-cache search cuda-toolkit | sort

또는 CUDA Downloads 에서 Linux → x86_64 → WSL-Ubuntu → 2.0 을 고르면, 그 조합에서 설치 가능한 Toolkit 버전이 페이지에 나온다. 일반 Ubuntu 용 cuda 메타패키지 말고 WSL-Ubuntu + cuda-toolkit-... 경로인지 꼭 확인한다.

정리하면 설치 버전은 이렇게 고른다.

  1. GPU CC 가 지원하는 Toolkit 범위
  2. nvidia-smiCUDA Version 이하
  3. WSL-Ubuntu 저장소/다운로드 페이지에 실제로 있는 버전

셋의 교집합에서 고르면 된다. 나는 GTX 950 + 드라이버 상한을 보고 Toolkit 을 맞췄다.

3. WSL 안에 Toolkit 만 설치

CUDA Toolkit 다운로드 에서 아래처럼 고른다.

  • Linux → x86_64 → WSL-Ubuntu → 2.0 → deb (network)

설치 페이지에 나오는 명령을 그대로 따라가면 된다. 대략 이런 형태다. (12-6 부분은 위에서 고른 버전으로 바꾼다.)

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-toolkit-12-6

중요한 건 cuda, cuda-12-x, cuda-drivers 같은 메타패키지가 아니라 cuda-toolkit-... 설치하는 것이다. 전자는 리눅스 드라이버까지 끌고 와서 WSL GPU 를 망가뜨린다.

PATH 도 잡아준다.

echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/lib/wsl/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc

nvcc --version

4. 동작 확인

간단한 샘플로 끝낸다.

cat <<'EOF' > hello.cu
#include <stdio.h>

__global__ void hello() {
  printf("hello from GPU thread %d\n", threadIdx.x);
}

int main() {
  hello<<<1, 4>>>();
  cudaDeviceSynchronize();
  return 0;
}
EOF

nvcc hello.cu -o hello
./hello

출력이 나오면 홈서버 CUDA 환경은 준비된 셈이다.

Tailscale

믿고 쓰는 Tailscale. 이번 홈서버를 구축하면서 Tailscale 에 원격 접속을 맡겼다.

Tailscale 은 WireGuard 기반 VPN 이다. 기기마다 에이전트를 설치하면 같은 Tailnet 에 묶이고, 공인 IP 나 포트포워딩 없이도 사설망처럼 서로 붙을 수 있다. NAT(집 공유기 뒤에 숨은 사설망) 뒤여도 대부분 자동으로 연결된다.

본가 데스크톱은 홈네트워크 안에 있고, 나는 캠퍼스·카페·기숙사 등 네트워크가 자주 바뀐다. 그때마다 라우터를 만지거나 공인 IP 를 신경 쓰기 싫어서, 맥북과 홈서버만 Tailscale 에 올려두고 tailscale ssh / Tailscale IP 로 접속하는 방식을 택했다.

원격 접속 자체는 이걸로 거의 끝난다.

WSL 에서 설치

Linux 설치 페이지 에 들어가면 아래 명령이 나온다. WSL 에서 그대로 실행한다.

curl -fsSL https://tailscale.com/install.sh | sh

설치 후 tailscale up 으로 로그인하면, WSL 을 켤 때마다 다시 붙는 식으로 쓸 수 있다.

이 상태만으로는 SSH 까지는 아니고, 한 번 더 실행해야 한다.

tailscale set --ssh

SSH inbound 정책은 더 섬세하게 조정할 수 있는데 나는 따로 하지 않았다. 필요하면 Tailscale SSH 문서 를 보면 된다.

맥북에서는 대략 이렇게 붙는다.

tailscale ssh <user>@<hostname>

이후에는 평소처럼 nvcc, make, git 작업을 서버에서 하면 된다.

장애복구성

SSH 는 이제 Tailscale 인증만 있으면 연결에 큰 문제가 없다. 연결 자체는 쉬웠는데, 문제는 내가 자취방에 있고 데스크톱은 본가에 있다는 것이다. 갑자기 서버에 문제가 생겨도 복구가 가능해야 했다.

물리적으로 거리가 있으니, 문제가 생겼을 때 부모님에게 컴퓨터 재부팅 정도만 부탁하면 되도록 만들고 싶었다.

그래서 데스크톱을 껐다가 켜기만 해도 자동으로 WSL 이 올라오고 Tailscale 이 붙게 했다.

Windows 작업 스케줄러(schtasks.exe) 를 활용했다. 아래 글을 보고 만들었고, 각자 리눅스 배포판에 맞게 명령어를 조금 수정하면 된다.

https://wikidocs.net/219903

이 작업이 다른 원격 서버 구축보다 더 중요했다. “접속 방법”보다 “누가 없을 때 어떻게 살리는가”가 더 작업을 늦추는 병목이 되기 때문이다.

마무리

정리하면 이렇다.

  1. Windows 드라이버 + WSL Toolkit 으로 CUDA 환경 만들기
  2. Tailscale SSH 로 어디서든 붙기
  3. 재부팅만으로 복구되게 자동화하기

Colab 의 %%writefile 지옥에서 벗어나, 맥북에서 평소처럼 코드를 쓰고 본가 GPU 로 돌리는 흐름이 목표였다. 아직 학기 중이고 실습용 서버로서 잘 버텨줬으면 좋겠다.

Comments