첫 번째 실패와 그 컨텍스트 보존하기
이 가이드는 성공적인 실행 이후부터 시작합니다. 즉, PyTorch가 장치를 인식하지만 애플리케이션이 특정 배치나 연산자에서 실패하는 상황입니다. 작은 계산조차 작동하지 않는다면 초기 진단부터 다시 시작하세요. 그렇지 않다면 첫 번째 오류, 반복 번호, 마지막으로 완료된 단계를 보존하세요. 첫 번째 실패 이후의 연속된 메시지들은 여러 독립적인 원인이 아니라 그 결과를 설명하는 것일 수 있습니다.
코드 리비전, Python 및 PyTorch 버전, 백엔드, 숫자 타입, 입력 형태를 기록해 두세요. 데이터의 경우 내용 전체를 복사하기보다 내부 식별자와 차원을 남기는 편이 좋습니다. 문제가 된 배치를 구별하는 요소를 찾아보세요. 길이, 누락된 타깃, 마지막의 불완전한 배치, 증강, 드물게 사용되는 분기 등입니다. 이 기록이 있으면 전체 캠페인을 다시 돌리지 않고도 해당 사례를 재현할 수 있습니다.
비동기성에도 불구하고 문제가 된 실행 지점 찾기
CUDA에서는 연산이 큐에 들어가 Python 함수가 반환된 뒤에 끝날 수 있습니다. 따라서 CPU로의 복사나 스칼라 읽기 중에 올라온 오류가 이전 계산에서 비롯된 것일 수 있습니다. PyTorch 문서에서 이 비동기 실행을 설명합니다. 트레이스가 가리키는 줄은 살펴봐야 할 관측 지점일 뿐, 항상 원인은 아닙니다.
NVIDIA/CUDA에서 짧게 재현하려면 CUDA_LAUNCH_BLOCKING=1을 사용한 별도 실행을 제안합니다. 이 옵션은 호출을 동기식으로 만들어 오류를 원인에 더 가깝게 좁힐 수 있습니다. 이는 진단용이며 시간 측정용이 아닙니다. 또한 주요 단계 사이에 임시로 동기화를 넣어 의심 구간을 줄일 수도 있습니다. 이후에는 이 계측을 제거하세요. 평소의 스케줄링을 바꾸기 때문입니다.
아래 명령은 설명용이며 실행되지 않았습니다. POSIX 터미널과 기존 train.py 스크립트를 가정합니다. 이 할당은 이번 실행에만 적용되며, 셸에 맞게 문법을 조정하세요. 이 NVIDIA 변수를 ROCm 스택에 일반화하지 마세요.
CUDA_LAUNCH_BLOCKING=1 python train.py성급히 결론 내리지 않고 오류 계열 읽기
메시지는 검색 범위를 좁혀줄 뿐 재현 가능한 사례를 대신하지 않습니다. 범위를 벗어난 인덱스, 잘못된 장치에 있는 텐서, 불가능한 할당은 각각 다른 점검이 필요합니다. 잘못된 데이터, 연산자 계약, 바이너리 환경 사이의 구분을 유지하세요. 배치, 정밀도, 라이브러리를 동시에 바꾸면 이 구분이 사라집니다.
장치에서 실행된 assertion 이후에는 같은 프로세스에서 같은 학습을 계속하려 하지 마세요. NVIDIA는 cudaErrorAssert가 기존 할당을 무효화하며 프로세스를 종료한 뒤 다시 실행해야 한다고 명시합니다. 노트북에서는 수정된 재현 전에 커널을 재시작해야 함을 의미합니다. 다만 재시작은 잘못된 타깃이나 유효하지 않은 인덱스를 고쳐주지는 않습니다.
표의 모든 열을 보려면 스크롤하세요.| 관찰된 단서 | 첫 번째 점검 | 피해야 할 결론 |
|---|---|---|
| device-side assert | 연산자의 단서, 타깃, 조건 | GPU가 반드시 고장 났다 |
| Out of memory | 형태, 텐서 수명, 프로세스 메모리 | 모든 CUDA 오류는 VRAM 부족이다 |
| 연산자 또는 커널 사용 불가 | 버전, 확장, 백엔드, dtype | 무작정 전부 재설치 |
| 서로 다른 장치 | 모델과 각 입력의 배치 위치 | 원인을 이해하지 않고 복사 추가 |
예시로 살펴보기: 네 개 클래스 문제에서의 클래스 4
출력이 네 개 열인 교육용 분류기를 가정해 봅시다. 클래스는 0부터 3까지 인덱스됩니다. 주석 파일에 값 4가 들어 있다면 1부터 4까지의 인코딩 또는 예상치 못한 다섯 번째 클래스를 시사할 수 있습니다. 출력 크기를 그냥 늘리면 제약은 사라지지만 주석의 의미는 해결되지 않습니다.
아래 제안된 점검은 타깃을 CPU로 전송하기 전에 적용됩니다. 실행되지는 않았습니다. long 타입 클래스 인덱스에 대한 CrossEntropyLoss 계약을 ignore_index=-100을 명시적으로 선택하여 보여줍니다. 확률 분포로 이루어진 타깃은 다루지 않습니다. 이 시나리오에서는 [0, 2, 4]가 거부되어야 하며, 이 예상 결과는 규칙에서 도출된 것이지 측정값으로 제시된 것이 아닙니다.
그다음 데이터 준비에서 매핑을 수정하고 클래스 이름과의 전단사 관계를 확인하세요. 모든 소스가 같은 규칙을 사용하는지 알기 전에는 일괄적으로 1을 빼지 마세요. 문제가 된 사례를 프로젝트와 함께 보관하는 작은 검증 세트에 추가하세요.
import torch
classes = 4
ignore_index = -100
target = torch.tensor([0, 2, 4], dtype=torch.long)
if target.ndim != 1 or target.dtype != torch.long:
raise ValueError("Cibles : vecteur d’indices attendu")
valid = target[target != ignore_index]
if valid.numel() == 0:
raise ValueError("Aucune cible exploitable dans ce batch")
if bool(((valid < 0) | (valid >= classes)).any()):
raise ValueError("Indice de classe hors domaine")트리거를 지우지 않고 프로그램 축소하기
먼저 동일한 변환으로 단일 입력 또는 단일 배치를 다시 실행하세요. 원격 추적, 결과 기록, 그리고 실패와 무관한 분기를 제거하세요. 의심되는 dtype, 형태, 연산자는 유지하세요. 오류가 특정 길이나 메모리 배치에 의존한다면, 임의의 작은 텐서로는 더 이상 재현되지 않을 수 있습니다.
한 번에 하나의 변경만 비교하세요: 선택적 확장 비활성화, 참조 연산자, 평소의 정밀도, 또는 CPU에서 존재하는 경우 동일한 연산을 CPU에서 실행. CPU에서의 성공은 단서일 뿐, CUDA 검증이 아닙니다. 사용자 정의 함수의 경우 strides, 연속성, 크기에 대한 가정도 기록하세요. 수정 전에는 실패하고 수정 후에는 성공하는 예제를 찾아, 예외가 없다는 것만이 아니라 출력을 검증하세요.
초기 범위에서 수정 검증하기
허용 가능한 수정은 최소 케이스, 인접 케이스, 그리고 원래 경로의 대표적인 부분을 통과해야 합니다. 특히 마지막 배치, 짧은 입력, 긴 입력, 매핑의 경계값을 다시 확인하세요. 거부된 요소가 식별 가능한지, 처리된 입력 수가 예상대로인지 확인하세요. 예외를 조용히 무시하면 눈에 보이는 크래시가 불완전한 결과로 바뀔 수 있습니다.
진단 모드를 제거하고, 새 프로세스에서 시작하여 정상 구성으로 동작을 확인하세요. 원인, 적용한 변경, 비회귀 검증을 기록하세요. 학습을 중단했다면, 오류 이전에 검증된 일관된 체크포인트에서 다시 시작하세요. 장애 중에 작성된 파일이 있다고 해서 재개가 보장되는 것은 아닙니다.
더 구체적인 분석이 필요할 때 판단하기
동일한 최소 케이스가 유효한 입력으로 실패한다면, 정확한 요청을 준비하세요: 연산, 형태, 타입, 백엔드, 버전, 그리고 첫 번째 관련 메시지. 개인 식별 정보와 불필요한 경로를 제거하세요. 바이너리 확장은 자체 호환성 매트릭스가 필요할 수 있습니다. PyTorch의 일반 지원이 이 확장을 자동으로 검증하지는 않습니다.
ROCm에서 PyTorch는 torch.cuda 인터페이스와 cuda 장치 이름을 유지합니다. NVIDIA 절차를 적용하기 전에 torch.version.hip로 이 스택을 식별하세요. 메시지, 도구, 진단 옵션은 다를 수 있습니다. 여기 설명된 어떤 점검도 준비된 환경이 Kernodeck 오퍼링과 호환됨을 증명하지 않습니다. GPU를 선택하기 전에 이러한 기준을 사용하여 필요 사항을 명확히 하세요.