1차 공개일 · 8월 20일1차 강의가 모두 공개됩니다
TECH 으로 돌아가기
TECH HACKER NEWS 오늘 10분 읽기 24 READS

VRAM 부족, 이제 크래시 대신 성능 저하로 끝난다 — 리눅스 7.3의 개선

게임을 돌리다 그래픽 카드의 VRAM이 모자라면 어떤 일이 벌어질까. 흔한 통념은 "끝났다"에 가깝다. 게임이 여기저기서 튕기고, 프레임은 사람이 못 견딜 수준으로 떨어지며, 정상적인 플레이가 불가능해진다는 것이다. 그런데 한 그래픽 드라이버 개발자가 올해 초부터 진행해 온 커널 작업이 마침내 업스트림에 병합되어 리눅스 7.3에 실린다. 이 작업의 핵심 메시지는 명확하다. VRAM 부족은 원칙적으로 안정성 문제가 아니라 성능 문제여야 하며, 실제로 그렇게 만들 수 있다는 것이다.

VRAM 초과 할당은 원래 성능만의 문제였다

GPU 드라이버에는 아주 오래전부터 VRAM 초과 할당(overcommit) 기능이 있었다. 드라이버가 이를 허용하면 애플리케이션은 원하는 만큼 VRAM을 요청할 수 있고, 커널 드라이버는 물리적으로 존재하는 메모리 안에 최대한 끼워 맞춰 준다. 문제는 요청량이 실제 VRAM 용량을 넘어서는 순간부터다. 이때 게임 메모리 일부는 CPU 쪽 시스템 RAM으로 밀려나는데(eviction), GPU 입장에서 CPU RAM 접근은 VRAM보다 훨씬 느리다. RAM 자체도 느린 데다 모든 접근이 PCI 버스를 거쳐야 하고, 이 버스가 대개 지연과 대역폭의 병목이 된다.

숫자로 보면 한계가 뚜렷하다. PCIe 4.0 x16 연결은 약 32GiB/s, 밀리초당 약 32.2MiB를 나른다. 최소 30FPS, 즉 프레임당 33.3ms를 기준으로 하면 GPU가 밀려난 메모리에서 끌어올 수 있는 데이터는 프레임당 약 1,075.5MiB, 겨우 1GiB를 조금 넘는 수준이다. 한 프레임에서 evict된 메모리를 1GiB 넘게 읽어야 한다면 30FPS는 물리적으로 불가능하다는 뜻이다. 반대로 말하면, 이 한계 안에만 머문다면 VRAM이 모자라도 성능이 반드시 무너지는 것은 아니다.

캐시가 만드는 차이

실제로 CPU 메모리를 조금 읽는 것 자체는 치명적이지 않다. 드라이버는 VRAM이 넉넉할 때조차 커맨드 버퍼 같은 데이터를 일부러 CPU RAM에 두기도 하는데, 이 경우엔 아무 문제 없이 돌아간다. 차이를 만드는 결정적 변수는 캐싱이다. 캐시에 적중하면 데이터가 CPU RAM에 있든 VRAM에 있든 접근 지연은 동일하다. RDNA3에서 측정한 마이크로벤치마크를 보면, 버퍼가 L2(약 6MB) 안에 들어가는 동안엔 두 메모리의 지연이 사실상 같다. L2를 벗어나면 CPU 메모리 접근은 접근당 약 2,400사이클까지 올라가는 반면 VRAM은 비슷한 범위에 머문다. 여기엔 VRAM만 거치는 인피니티 캐시의 역할이 있다. CPU 메모리는 L2 미스 시 인피니티 캐시를 타지 못하고 곧장 PCIe로 향한다. 측정치로는 PCIe 페치가 인피니티 캐시 적중보다 약 7.3배, VRAM 페치보다 약 4.6배 더 느렸다.

결국 어느 메모리가 밀려나느냐가 중요해진다. 캐시 친화적으로 접근되는 메모리나 자주 읽히지 않는 메모리는 evict돼도 타격이 작다. 수 GiB짜리 할당이라도 GPU가 그중 일부만 실제로 읽는다면, 프레임당 1GiB라는 한계선에는 한참 못 미친 채 넘어갈 수 있다. 무엇이 얼마나 접근되고 얼마나 잘 캐싱되느냐에 따라, VRAM을 초과해도 성능을 완전히 망치지 않는 경우가 실제로 존재한다는 것이다.

이론과 현실 사이 — 커맨드 제출이 튕기는 이유

하지만 SteamOS에서 설정을 올려 보면 이론과 다른 벽에 부딪힌다. "radv/amdgpu: Not enough memory for command submission"이라는 오류다. 흥미로운 점은 이것이 일반적인 할당 실패가 아니라는 것이다. RADV는 커맨드를 제출할 때 커널이 -ENOMEM을 반환하면 이 메시지를 띄우는데, 커맨드 제출은 새 리소스를 할당하지 않는다. 커맨드 버퍼는 이미 미리 할당돼 성공한 상태다. 모든 메모리가 정상 할당됐는데도 그걸 GPU 제출에 쓰는 순간 메모리 부족이 튀어나오는 셈이다.

원인은 접근성 보장 과정에 있다. amdgpu는 매 제출마다 GPU가 참조할 수 있는 모든 메모리가 접근 가능하도록 만든다. 최신 바인드리스 그래픽 API에서는 할당된 모든 메모리가 참조될 수 있다고 가정해야 하기 때문이다. 대부분의 할당은 CPU RAM이든 VRAM이든 상관없지만, 일부는 반드시 VRAM에만 있어야 한다. 이런 할당이 다른 앱 때문에 시스템 RAM으로 밀려나 있으면 amdgpu는 이를 VRAM으로 되돌려야 하고, 남는 VRAM이 없으니 다른 무언가를 또 evict해야 한다. 그런데 이 eviction이 실패하면서 커널이 메모리 부족을 보고한다.

데드락과 빠져 있던 재시도 루프

왜 eviction이 무작위로 실패할까. 메모리를 밀어내려면 해당 할당의 락을 잡아야 하는데, 제출 과정에서도 참조되는 모든 할당을 잠가 다른 앱이 그 사이 메모리를 옮기지 못하게 막는다. 두 GPU 제출이 동시에 서로가 잠근 할당을 원하면 전형적인 ABBA 데드락이 생긴다. 커널은 이를 해결할 방법을 안다. 락 획득을 트랜잭션으로 묶어 두고, 데드락이 감지되면 한쪽을 "wounded"로 표시해 다음 락 시도에서 -EDEADLCK를 돌려준다. 이 신호를 받으면 잡은 락을 모두 풀고 트랜잭션을 처음부터 다시 시작하면 된다. 견고하게 잘 작동하는 방식이다. 실제로 구현돼 있기만 하다면.

그래픽 서브시스템은 이 wound-abort-retry 루프를 drm_exec라는 헬퍼로 추상화한다. 그런데 리눅스 공용 GPU 메모리 관리 계층인 TTM의 락 코드에는 drm_exec가 거의 쓰이지 않았고, 오히려 -EDEADLCK가 나면 eviction이 실패한다는 주석까지 달려 있었다. 강한 메모리 압박 아래 데드락이 발생하는 순간 커널이 재시도 대신 제출을 거부해 버렸던 것이다. TTM에 drm_exec를 연결하려는 패치셋은 2024년에도 올라왔지만 남은 버그 탓에 병합되지 못했다. 개발자는 이 패치셋을 자기 커널 버전에 리베이스하고, 게임이 무거운 VRAM 경합 3분 만에 무작위로 멈추는 버그를 한 주간의 고생 끝에 잡아냈다. 다만 그가 고친 버전을 다시 제출했음에도 병합까지는 아직 더 손봐야 한다고 밝혔다.

실무자에게 남는 의미와 한계

정리하면 리눅스 7.3에 들어가는 것은 초과 할당 자체를 빠르게 만드는 마법이 아니라, VRAM이 모자랄 때 앱이 무작위로 죽지 않도록 안정성 바닥을 다지는 작업이다. 이제 크래시라는 변수가 빠졌으니 비로소 순수한 성능 튜닝을 논할 수 있게 됐다. 다만 크래시를 없앤 뒤 실제로 설정을 올려 보면 초기 성능은 여전히 형편없었고, 개발자는 커널 드라이버가 무엇을 그리 느리게 하는지 gpuvis의 커널 트레이스포인트로 타임라인을 뜯어보며 원인을 찾는 단계로 넘어갔다. VRAM 부족 상황을 다루는 유저 스페이스와 커널의 협업은 아직 진행형이라는 뜻이다.

VRAM이 빠듯한 환경에서 리눅스 게이밍을 다루는 실무자라면 두 가지를 기억할 만하다. 첫째, 성능 한계는 PCIe 대역폭과 접근 패턴, 캐시 적중률이 함께 결정하며 프레임당 1GiB 남짓이라는 물리적 상한이 있다. VRAM 초과가 곧 재앙이라는 통념은 워크로드에 따라 얼마든지 달라진다. 둘째, 그동안 겪던 상당수의 "메모리 부족" 제출 실패는 실제 용량 부족이 아니라 커널 eviction 경로의 데드락 처리 누락에서 비롯됐다. 리눅스 7.3과 후속 TTM 패치가 자리를 잡으면 그 원인 중 하나가 정면으로 해소된다는 점은, 커널 버전을 선택하고 문제를 진단하는 데 실질적인 참고가 된다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://pixelcluster.dev/VRAM-Overcommit/
SHARE
NEXT · CHOOSE

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

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

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