손실이 줄지 않거나, 비싸게 빌린 GPU의 활용률이 30%에 머문다면 학습 내부를 들여다봐야 한다. 먼저 두 도구의 관심사를 명확히 가른다.
구분
SageMaker Debugger
SageMaker Profiler
보는 것
모델 내부 텐서(그래디언트, 가중치, 손실, 활성값)
시스템 자원(CPU/GPU 활용률, 메모리, I/O)
답하는 질문
"모델이 왜 잘못 학습되나?"
"왜 느린가/비효율적인가?"
대표 감지
그래디언트 소실/폭발, 과적합, 가중치 미갱신
GPU 저활용, 데이터 로딩 병목, CPU 병목
동작 방식
텐서를 주기적으로 S3에 저장 후 규칙(rule) 평가
시스템·프레임워크 메트릭 수집·분석
자동 조치
규칙 위반 시 알림/조기 종료(action)
병목 리포트·권고
핵심 직관: Debugger는 "모델이 잘못됐다"를, Profiler는 "자원이 낭비된다"를 본다.
"그래디언트가 0이 됐다/폭발한다" 같은 학습 품질 증상 → Debugger.
"GPU가 놀고 있다/데이터 로딩이 느리다" 같은 자원 증상 → Profiler.
증상을 먼저 계층으로 분류한다 손실·정확도가 이상하다 → 모델 계층 → Debugger (텐서) │ 학습은 되는데 느리다/비싸다 → 자원 계층 → Profiler (GPU/CPU/IO) │ 작업 상태·전체 추세를 보고 싶다 → 운영 계층 → CloudWatch (메트릭·로그·알람)
이 분리는 관측가능성(observability)의 두 층위에 대응한다. Debugger는 모델이라는 "수학적 프로세스"의 내부 상태(텐서)를 본다 — 그래디언트가 소실되면 학습이 멈추고 폭발하면 발산한다. Profiler는 그 프로세스가 돌아가는 "물리적 자원"의 사용 패턴을 본다 — GPU가 데이터를 기다리며 노는지, 전처리가 CPU를 묶고 있는지. 두 층위를 같이 봐야 "왜 학습이 안 되는가"와 "왜 비싼가"를 동시에 푼다.
개념: 규칙은 학습 밖에서 돈다. Debugger 내장 규칙은 학습 컨테이너 안이 아니라 별도의 평가 작업으로 실행된다. 학습은 텐서를 S3에 쓰기만 하고, 규칙은 그 텐서를 읽어 판정한다. 덕분에 규칙 평가가 학습 속도를 크게 갉아먹지 않지만, 그만큼 판정에 약간의 지연이 있고 별도 리소스 비용도 붙는다는 점을 같이 기억한다.
⚠️ 함정: 규칙은 기본적으로 "감지 후 보고"만 한다. 규칙이 위반됐을 때 학습을 자동으로 멈추려면 action을 따로 연결해야 한다. 예를 들어 그래디언트가 폭발하는데도 학습이 끝까지 돌면서 비용만 태우는 사고를 막으려면 StopTraining 액션을 건다. "감지=자동중단"이라고 착각하지 않는 게 핵심.
from sagemaker.debugger import Rule, rule_configsfrom sagemaker.debugger import CollectionConfig# 규칙 위반 시 학습 자동 중단 + 알림rule = Rule.sagemaker( rule_configs.loss_not_decreasing(), actions=rule_configs.ActionList( rule_configs.StopTraining(), # 학습 중단(비용 절약) rule_configs.Email("ml-team@example.com") ))
전형적 처방: GPU 활용률이 낮고 데이터 로딩이 병목이면 → DataLoader worker 수 증가, 데이터를 FSx for Lustre로 캐시, 전처리를 학습과 비동기로(프리페치).
⚠️ 함정: "학습이 느리다 → 더 비싼 GPU 인스턴스로 바꾼다"는 보기는 대부분 오답이다. GPU가 이미 놀고 있다면 더 빠른 GPU를 붙여도 노는 시간만 늘 뿐이고 비용만 오른다. 인스턴스 업그레이드는 Profiler로 "GPU 연산 자체가 포화"임을 확인한 뒤의 선택이다.
GPU 저활용의 본질은 "GPU가 노는 시간"이다. 학습 한 스텝은 데이터 로딩 → 전처리 → forward → backward → 옵티마이저로 이어지는데, GPU는 forward/backward만 한다. 나머지 단계가 느리면 GPU는 기다린다. 그래서 데이터 파이프라인(로딩·전처리)을 GPU 연산과 겹치게(overlap) 만드는 프리페치·비동기 로딩이 활용률을 끌어올린다. Profiler는 이 "기다리는 시간"을 가시화해 어느 단계를 고칠지 알려준다.
한 팀이 ml.p4d 인스턴스로 학습하는데 GPU 활용률이 25%에 머물러 학습이 예상보다 4배 느렸다. Profiler 리포트를 보니 GPU가 대부분 데이터 로딩을 기다리고 있었다. 원인은 매 배치를 S3에서 직접 읽고 CPU 전처리가 무거웠던 것. DataLoader worker를 늘리고 데이터를 FSx for Lustre에 캐시한 뒤 전처리를 프리페치로 겹치자 GPU 활용률이 85%로 올라 학습 시간이 1/3로 줄었다. 교훈: 느린 학습이 항상 GPU 성능 문제는 아니다 — Profiler로 진짜 병목을 먼저 본다.
증상이 무엇인가? ├─ 손실 정체 / 그래디언트 소실·폭발 / 과적합 │ → Debugger 내장 규칙 (+ StopTraining action으로 비용 차단) ├─ 느리다 / GPU가 논다 / 비용 대비 비효율 │ → Profiler로 병목 진단 → 데이터 파이프라인·배치·정밀도 조정 │ (GPU 연산 포화가 확인된 뒤에야 인스턴스 업그레이드) └─ 전체 추세·실패 알림·여러 작업 비교 → CloudWatch 메트릭/로그/알람 (+ EventBridge로 후속 자동화)
다음 글에서는 학습이 끝난 모델이 정말 좋은지 판단하는 모델 평가 — 지표 선택과 과적합·교차검증 —를 본다.