Apple Silicon

Apple Silicon

Apple Silicon(M 시리즈) 칩은 CPU와 GPU가 같은 메모리 풀을 공유하는 통합 메모리 아키텍처(unified memory architecture)를 가집니다. 메모리를 공유하면 GPU의 데이터 전송 오버헤드가 사라져서, 큰 모델을 로컬에서 훈련하는 것이 실용적이게 돼요. Transformers는 이 하드웨어에서 훈련을 가속화하기 위해 Metal Performance Shaders (MPS) 백엔드를 사용합니다.

출처: 문서

본문

이를 위해서는 macOS 12.3 이상과 MPS를 지원하도록 빌드된 PyTorch가 필요해요.

[!WARNING] MPS는 아직 모든 PyTorch 연산을 지원하지 않습니다 (누락된 연산에 대한 자세한 내용은 이 GitHub 이슈를 보세요). 지원하지 않는 연산은 PYTORCH_ENABLE_MPS_FALLBACK=1로 설정하면 CPU 커널로 대체(fallback)될 수 있어요. 그 외 예상치 못한 동작은 PyTorch 저장소에 이슈를 열어 주세요.

모델 로딩과 기기 선택 (Model loading and device selection)

MPS는 모델 전체가 통합 메모리에 들어가야 하므로, device_map="auto"가 CUDA처럼 레이어를 CPU로 오프로드할 수 없습니다. 이런 경우 더 작은 모델을 쓰는 것을 시도해 보세요.

가중치를 MPS로 로딩하는 것은 safetensors 0.8.0과 PyTorch 2.9 이상에서 더 빠르고 메모리 사용도 적습니다. device_map="mps"나 "auto"로 설정하면 가중치가 중간 복사 없이 Metal 버퍼에 매핑되어, 로딩 중 메모리 사용량이 대략 절반으로 줄고 속도는 약 5~6배 빨라져요. 더 오래된 PyTorch 버전에서는 표준 로딩 경로로 대체됩니다.

Trainer는 torch.backends.mps.is_available로 MPS를 자동 감지해, 설정 변경 없이 기기를 mps로 설정합니다.

혼합 정밀도 (Mixed precision)

MPS는 bf16과 fp16 혼합 정밀도를 모두 지원합니다 (bf16은 macOS 14.0 이상 필요).

from transformers import TrainingArguments

training_args = TrainingArguments(
    output_dir="./outputs",
    bf16=True,  # requires macOS 14.0+
)

그래프 캐시 (Graph cache)

MPS는 고유한 텐서 형태마다 별도의 Metal 커널을 컴파일하고, 이를 제거(eviction) 정책 없이 그래프 캐시에 저장합니다. 가변 길이 입력(패딩된 시퀀스, 동적 배치)으로 훈련하면 새로운 형태가 나올 때마다 캐시가 커져서 결국 통합 메모리를 소진할 수 있어요.

이런 성장을 제한하려면 TrainingArguments에서 torch_empty_cache_steps를 설정하세요. MPS에서 Trainer는 torch_empty_cache_steps 스텝마다 기기 캐시와 함께 그래프 캐시도 비우는데, 처리량(throughput) 비용이 발생합니다. 두 캐시를 모두 비우려면 옵트인(opt-in)해야 해요. torch_empty_cache_steps를 설정하지 않으면(기본값) 두 캐시 모두 비워지지 않아 동작이 바뀌지 않습니다.

from transformers import TrainingArguments

training_args = TrainingArguments(
    output_dir="./outputs",
    torch_empty_cache_steps=1,  # clear caches every step
)

그래프 캐시를 비우려면 PyTorch 2.13 이상이 필요합니다. 더 오래된 버전에서는 Trainer가 그래프 캐시 호출을 건너뛰고 기기 캐시만 비워요.

다음 단계 (Next steps)

더 알아보기 (Learn more)