soobook
GPU

NVIDIA XID Errors

GPU 커널 로그의 XID를 읽고 분류해서 자동 복구로 바꾸는 클러스터 운영 관점

XID는 NVIDIA 드라이버가 커널 로그에 남기는 GPU 오류 리포트다. 자동차의 체크엔진 경고등처럼, 숫자 하나로 “GPU에 뭔가 생겼다”를 알린다.

수천 장의 GPU를 돌리는 클러스터에서 장애는 예외가 아니라 상수다.

문제는 GPU가 고장 날 때 친절한 신호가 나오지 않는다는 점이다.

대신 커널 로그에 이런 줄이 하나 찍힌다.

NVRM: XID (PCI:0000:03:00): 79, pid=..., GPU has fallen off the bus.

79가 XID 코드다. 코드만 보고 원인을 단정할 수는 없지만, 어떤 조치가 필요한지를 판단하는데 도움이 된다.

What Is an XID

XID는 NVIDIA 드라이버가 GPU에서 오류를 감지했을 때 운영체제의 커널 로그에 출력하는 오류 리포트다.

NVIDIA 공식 문서는 그 성격을 하드웨어 문제, 드라이버 문제, 유저 애플리케이션 문제 세 가지로 나눈다. XID는 이 셋 중 하나의 신호일 수 있다.

같은 코드는 드라이버 버전이 바뀌어도 같은 의미를 유지한다.

XID 79는 어느 클러스터에서든 “GPU가 PCIe 버스에서 사라졌다”는 뜻이다.

Linux에서 XID는 커널 로그 버퍼에 쌓이고, 배포판에 따라 /var/log/syslog/var/log/messages, journald로 흘러간다.

# 커널 로그에서 모든 XID 메시지를 찾는다
grep 'NVRM: XID' /var/log/syslog
journalctl -k | grep -i XID

메시지 한 줄은 이렇게 뜯어볼 수 있다.

NVRM: XID (0000:03:00): 48, ...
              │            └── XID 코드 (48 = Double Bit ECC)
              └── PCIe 주소 (bus:device.function)

앞의 0000:03:00은 어느 GPU인지를 가리키는 PCIe 주소이고, 뒤의 숫자가 무슨 일이 일어났는지를 가리키는 XID 코드다.

GPU 드라이버가 커널 로그에 남긴 XID 한 줄이 어떻게 조치로 이어지는지. GPU fault가 NVRM XID 메시지로 커널 로그에 찍히면 dmesg, nvidia-smi, DCGM 세 수집 경로가 이를 읽고, 코드별 심각도로 분류한 뒤, 앱 재시작부터 노드 drain까지 자동 조치로 연결된다

Reading the Code

XID 코드는 100개가 넘는다. 하지만 실전에서 매일 마주치는 코드는 소수다. NVIDIA의 최신 카탈로그(Ampere 이후 세대 기준)는 각 코드에 즉시 조치(Resolution Bucket)를 붙여둔다. 이 조치 값이 사실상 “이 코드는 얼마나 심각한가”를 알려주는 지표다.

XID의미즉시 조치성격
13Graphics Engine Exception앱 재시작대개 앱 버그(배열 out-of-bounds)
31GPU memory page fault앱 재시작대개 앱 버그(잘못된 주소 접근)
43GPU stopped processing무시GPU는 정상, 앱만 종료됨
48Double Bit ECC (DBE)리셋 / 리부팅복구 불가 메모리 오류
63Row remapping event무시재매핑이 정상 동작한 기록
64Row remapping failureGPU 리셋재매핑 기록 실패, 위험
74NVLink error리셋 / 리부팅링크 또는 원단 GPU 문제
79GPU has fallen off the bus리부팅PCIe 링크 다운, 고전적 치명 오류
92High single-bit ECC rate무시(조사)SBE 과다, 임계 초과 시 RMA
94Contained memory error앱 재시작해당 앱만 영향(A100 이후)
95Uncontained memory errorGPU 리셋여러 앱에 영향, 리셋 필요
119 / 120GSP RPC timeout / GSP errorGPU 리셋GSP 코어 문제
140Unrecovered ECC errorGPU 리셋페이지 오프라인 처리 실패
154GPU Recovery Action Changed(메타)다른 XID의 필요 조치를 요약

XID 154는 비교적 최근에 추가됐고 운영자에게 특히 유용하다. NVIDIA가 내부적으로 판정한 복구 수준을 그대로 외부에 노출하기 때문이다. None, Drain P2P, Drain and Reset, GPU Reset Required, Node Reboot Required 같은 값으로, “리부팅해야 함”을 드라이버가 직접 말해준다.

Codes That Dominate at Scale

실제로 문제를 일으키는 코드만 살펴보자.

XID 79(GPU has fallen off the bus)는 가장 보기 싫은 녀석이다. 드라이버가 PCIe로 GPU에 접근하려는데 GPU가 응답하지 않는 상태다. PCIe 링크의 하드웨어 문제이거나 GPU 자체가 죽은 경우가 많다. 클라우드 프로바이더들이 “치명(critical)“으로 분류하고 노드를 자동으로 비우는 대표 코드다.

XID 48(Double Bit ECC)과 94/95(Contained / Uncontained memory error)는 메모리 오류 계열이다. 이 계열에서 중요한 건 코드 하나가 아니라 코드가 나오는 순서다. DBE(48) 뒤에 재매핑 이벤트(63)가 따라오면 GPU가 불량 메모리 행을 스스로 재매핑한 것이라 리셋으로 복구할 수 있다. 반면 재매핑 실패(64)가 따라오면 GPU를 신뢰할 수 없어 리부팅이나 교체로 넘어가야 한다.

XID 13(Graphics Engine Exception)은 흔하지만 대개 하드웨어 문제가 아니다. 유저 코드가 배열 끝을 넘어 접근하는 것 같은 애플리케이션 버그에서 나온다.

ECC and Row Remapping

메모리 오류 계열을 이해하려면 ECC와 row remapping을 알아야 한다.

ECC(Error Correcting Code)는 GPU 메모리(HBM)가 비트 오류를 감지하고 정정하는 메커니즘이다. 한 비트 오류(Single Bit Error)는 하드웨어가 정정하고 넘어가지만, 두 비트 오류(Double Bit Error)는 정정할 수 없다. 이 복구 불가 오류가 XID 48로 올라온다.

Ampere 세대부터 GPU는 row remapping으로 불량 메모리 행을 대체할 수 있다. 특정 행에서 오류가 반복되면 그 행을 예비 행으로 갈아끼우는 방식이다. 이때 재매핑이 기록되면 XID 63, 기록에 실패하면 XID 64가 나온다. nvidia-smi -q로 이 상태를 직접 볼 수 있다.

Remapped Rows
    Correctable Error   : 0    # 정정 가능, 무시해도 됨
    Uncorrectable Error : 0    # 0보다 크면 XID 로그 확인
    Pending             : No   # Yes면 리셋/리부팅으로 재매핑 활성화 필요
    Remapping Failure   : No   # 항상 No여야 함. Yes면 GPU 교체 대상

복구 가능 여부는 XID 48 다음에 오는 이벤트가 가른다. Double Bit ECC 오류 뒤에 재매핑 기록(XID 63)이 따라오면 리셋으로 되살려 다시 쓸 수 있고, 재매핑 실패(XID 64)가 따라오면 GPU를 신뢰할 수 없어 drain과 교체(RMA)로 넘어간다

A100 이후에는 error containment도 더해진다. 메모리 오류가 났을 때 그 오류를 일으킨 애플리케이션 하나에만 가두면 XID 94(contained), 가두지 못하고 여러 애플리케이션으로 번지면 XID 95(uncontained)다. Contained면 해당 앱만 다시 띄우고 나머지는 그대로 두면 되지만, uncontained면 GPU 전체를 리셋해야 한다.

이 계열의 심각도 사다리는 대략 이렇다. 정정 가능한 단일 비트 오류는 무시, 재매핑으로 흡수되면 리셋으로 복구, 재매핑이 실패하거나 SRAM DBE가 임계를 넘으면 GPU 교체(RMA)로 넘어간다.

Detecting XID in a Cluster

커널 로그의 한 줄을 사람이 매번 grep할 수는 없다. 클러스터에서는 이 신호를 자동으로 수집한다.

nvidia-smi -q는 ECC 카운트와 재매핑 상태를 보여준다. 여기서 한 가지 함정이 있다. ECC 카운트에는 드라이버를 다시 올린 뒤부터 센 Volatile과 GPU 수명 전체를 센 Aggregate가 있다. 장비를 켰을 때 Aggregate 카운트가 0이 아니라고 해서 지금 활성 장애가 있다는 뜻은 아니다.

DCGM(Data Center GPU Manager)은 GPU 헬스 모니터링의 표준 도구다. dcgmi diag로 진단을 돌리고, dcgm-exporter가 메트릭을 Prometheus로 내보낸다. XID는 DCGM_FI_DEV_XID_ERRORS라는 메트릭으로 노출되는데, 이 값은 마지막으로 관측된 XID 코드를 담는다(오류가 없으면 0).

# Prometheus alert 예시
DCGM_FI_DEV_XID_ERRORS > 0

이 메트릭에도 함정이 있다. GPU가 회복돼도 값이 자동으로 0으로 돌아가지 않고 마지막 코드를 계속 붙들고 있는 sticky 동작이 알려져 있다. 알림 룰을 짤 때 이 점을 감안해야 하고, 필요하면 exporter 파드를 재시작해서 값을 리셋한다.

Kubernetes에서는 이 신호들이 노드 상태로 연결된다. NVIDIA의 device plugin과 node-problem-detector가 XID를 파싱해 노드를 unhealthy로 표시하고, 그 노드를 cordon하고 drain해서 새 워크로드가 배치되지 않게 막는다. Modal 같은 서비스는 치명 XID(대표적으로 79)를 감지하면 워커를 자동으로 비우고 컨테이너를 다른 호스트로 옮긴다.

Remediation Playbook

지금까지의 내용을 실제 조치 순서로 묶으면 이렇게 된다. NVIDIA, AWS, 클라우드 프로바이더의 가이드가 대체로 수렴하는 그림이다.

XID 코드의 심각도에 따라 조치 수준이 정해지는 에스컬레이션 사다리. 앱 버그 계열은 프로세스만 다시 띄우고, 복구 가능한 메모리 오류는 GPU를 리셋하며, 버스 이탈이나 재매핑 실패는 노드를 비우고 리부팅하고, 임계를 넘은 하드웨어 손상은 GPU 교체로 넘어간다

  1. 앱 재시작: XID 13, 31, 43, 94처럼 GPU 자체는 멀쩡한 경우. 프로세스만 다시 띄운다. 필요하면 cuda-gdb나 Compute Sanitizer의 memcheck로 유저 코드를 디버깅한다.
  2. GPU 리셋: XID 64, 95, 119, 120처럼 GPU 상태를 초기화하면 복구되는 경우.
    sudo nvidia-smi -i <GPU_UUID> -r
  3. 노드 cordon / drain: k8s에서 노드를 unhealthy로 표시하고 새 파드 배치를 막은 뒤, 기존 작업이 끝나기를 기다린다.
  4. 노드 리부팅: XID 48, 79, 또는 XID 154가 “Node Reboot Required”를 말할 때. 리부팅으로 불량 페이지를 정리하거나 재매핑을 활성화한다.
  5. 호스트 마이그레이션: 재매핑 실패(Remapping Failure: Yes)처럼 그 GPU를 더는 쓸 수 없을 때, 정상 GPU를 가진 다른 호스트로 옮긴다.
  6. GPU 교체(RMA): SRAM DBE가 임계를 넘거나, 리셋과 리부팅으로도 반복해서 오류가 나는 경우. 필드 진단을 돌리고 하드웨어 벤더에 넘긴다.

References