TECH 으로 돌아가기
TECH HACKER NEWS 오늘 8분 읽기 26 READS

KVM 게스트에서 엔비디아 GPU를 거의 원본 성능으로 쓰는 virtio-nvgpu

KVM 게스트에서 엔비디아 GPU를 거의 원본 성능으로 쓰는 virtio-nvgpu
SOURCE IMAGE · HACKER NEWS

가상머신에서 엔비디아 GPU를 공유하는 문제는 오래된 골칫거리다. 지금까지는 GPU 하나를 통째로 한 VM에 넘기는 VFIO 패스스루로 성능을 얻거나, 그래픽 API 호출을 게스트에서 직렬화해 호스트에서 재생하는 방식으로 공유성을 얻는, 둘 중 하나를 택해야 했다. nestrilabs가 공개한 실험적 프로젝트 virtio-nvgpu는 이 절충을 다른 지점에서 끊으려 한다. 그래픽 API가 아니라 커널 드라이버 ABI 수준, 즉 /dev/nvidia* 장치로 향하는 ioctl 단위에서 게스트와 호스트 사이를 중계한다는 것이 핵심이다.

구조상의 차이는 성능에 직접 반영된다. 게스트는 엔비디아의 정식 사용자 모드 드라이버를 수정 없이 그대로 돌린다. 같은 라이브러리, 같은 Vulkan과 NVENC가 같은 카드와 대화한다. 이 드라이버들은 GPU 커맨드 버퍼를 게스트 안에서 로컬로 만들기 때문에 개별 드로우 콜이 경계를 넘어가지 않는다. 실제 제출은 드라이버가 미리 매핑해 둔 메모리에 쓰는 동작이고, 그 메모리는 호스트의 것이다. 그래서 렌더 루프가 도는 동안에는 사실상 아무것도 중계되지 않는다. 프로젝트 측 측정에서 813,691프레임 동안 백엔드가 처리한 메시지는 13,792건, 즉 59프레임당 한 번 경계를 넘었고 그마저 대부분은 초기 장치 설정이었다고 한다.

측정된 숫자

측정은 RTX 3060, 드라이버 595.99.02 환경에서 이뤄졌다. 동일한 헤드리스 Vulkan 부하를 베어메탈과 게스트에 걸었을 때, 한 프레임에 약 2ms 이상 걸리는 구간, 다시 말해 게임이 실제로 그리는 대부분의 프레임에서는 게스트가 베어메탈의 2% 이내 성능을 냈다. 그보다 가벼운 프레임에서는 GPU를 기다리는 비용이 드러나는데, 게스트가 GPU를 기다렸다 깨어나는 데 약 0.02ms가 프레임 크기와 무관하게 든다. 프레임 자체가 거의 존재하지 않을 만큼 짧을 때 이 대기 비용이 상대적으로 커진다는 뜻이다.

GPU 공유의 실익은 게스트가 CPU를 얼마나 아끼느냐에 달려 있다. 여기서도 게스트의 CPU 비용은 호스트와 같다고 보고됐다. 더 눈에 띄는 것은 여러 게스트를 붙였을 때다. RTX 3060 하나에 같은 부하를 건 네 개의 게스트가 각각 25.84, 26.49, 25.57, 25.79fps를 냈고 합계는 103.7fps로, 단일 게스트의 102.9fps와 거의 같았다. p50 프레임 타임은 네 게스트 모두 39.165ms 안팎으로 소수점 넷째 자리까지 고르게 갈렸다. 넷 모두 동시에 정상 렌더링하며 각각 60Hz로 H.264를 인코딩했고 NVENC 세션 한계에도 걸리지 않았다. 다만 개발자는 넷이 한계가 아니라 그저 그만큼만 돌려봤다는 점을 분명히 한다.

어떻게 동작하나

게스트 측 커널 드라이버는 /dev/nvidiactl, /dev/nvidia0…N, /dev/nvidia-uvm를 등록하고 ioctl을 제어용 virtqueue에 직렬화하며 mmap 요청에는 공유 메모리 영역을 올바른 캐싱 속성으로 매핑한다. 이 드라이버는 바이트를 옮길 뿐 ABI 판단은 하지 않는다. 판단은 호스트 쪽 device 크레이트가 맡아, 게스트 핸들을 호스트 장치 파일 디스크립터로 매핑하고 ioctl 인자 안에 박힌 포인터와 FD를 ABI에 맞게 다시 쓴 뒤 호스트 장치에 발행한다. 두 번째 virtqueue는 반대 방향으로 이벤트를 나른다. 호스트가 열어 둔 디스크립터가 읽기 가능해지면 이를 알려 GPU를 기다리던 게스트를 깨우는데, 이 경로가 없으면 게스트는 대기 자체를 못 하고 항상 준비 완료로 보고되는 디스크립터를 폴링하며 CPU를 태운다.

라이선스는 세 구역으로 나뉜다. 커널 심볼을 건드려야 하는 게스트 절반은 GPL, 다른 사람이 위에 얹어 만들 수 있도록 호스트 절반은 관대한 라이선스, 양쪽이 공유하는 정의는 양쪽에서 포함할 수 있게 배치했다. 이 구성은 같은 문제를 푼 chromeos/virtio-media의 레이아웃을 따른 것으로, device 크레이트는 특정 VMM에 의존하지 않고 몇 개의 트레이트만 구현하면 채택할 수 있게 설계됐다. 반면 게스트 프로세스마다 샌드박스 헬퍼를 하나씩 두어 권한 없이 ioctl을 발행하려는 'isolate' 구성 요소는 아직 설계만 있고 코드는 없다. 지금은 백엔드가 VMM 프로세스 안에서 장치 디스크립터를 직접 쥐고 있다.

실무자가 짚어야 할 한계

가장 취약한 지점은 엔비디아 커널 드라이버 ABI가 안정적이지 않다는 사실이다. 릴리스마다 ioctl 구조체 레이아웃이 바뀐다. virtio-nvgpu는 지원 버전을 명시적으로만 인정한다. 현재 ABI 프로파일은 535.129.03, 580.178.04, 595.71.05이며 범위로 매칭해, 두 프로파일 사이의 버전은 낮은 쪽을, 마지막보다 새 드라이버는 마지막 프로파일을 쓴다. 535.129.03보다 오래된 것은 추측 대신 거부한다. 레이아웃을 본 적 없는 ioctl을 중계하면 오류 대신 그럴듯한 오답이 나오기 때문이다. 최신 드라이버가 오작동하면 가장 먼저 의심할 대목이 바로 이 '변한 게 없을 것'이라는 가정이다. 구조체 정보는 엔비디아의 open-gpu-kernel-modules에서 태그별로 기계적으로 추출하고, 어떤 명령이 안전한지에 대한 판단은 gVisor의 nvproxy 상류를 따라가 유지 비용을 묶어 두려 한다.

정리하면 이 프로젝트는 API 호출마다 경계를 넘는 Venus 방식이나 GPU 전체를 한 VM에 묶는 VFIO와 달리, 멀티테넌트 환경에서 엔비디아 GPU를 헤드리스 스트리밍에 나눠 쓰려는 목표에 정확히 겨눠져 있다. 다만 측정은 카드 한 종, 드라이버 한 버전, 합성 부하 하나로 이뤄졌고 다른 하이퍼바이저와의 비교는 아예 수행되지 않았다. A2000(615.71.09)은 렌더링은 되지만 벤치마크되지 않았다. 그 이상은 검증되지 않은 영역이며, 아직 '실험적'이라는 꼬리표가 정직하게 붙어 있는 상태다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://github.com/nestrilabs/virtio-nvgpu
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기
처리 중...