Model parallel
다중 GPU에 학습을 분산하는 두 가지 방법으로 모델을 나누는 것과 데이터를 나누는 방법이 있다.
- 모델을 나누는 것은 alexnet에서 사용한 것처럼 생각보다 예전보다 썼다
- 모델의 병목, 파이프라인의 어려움 등으로 인해 모델 병렬화는 고난이도 과제이다
데이터를 나누는 것은 데이터를 나눠서 GPU에 할당 후 결과의 평균을 취하는 방법이다
- minibatch 수식과 유사한데 한 번에 여러 GPU에서 수행
PyTorch에서는 DataParallel, DistributedDataParallel 두 가지 방식을 제공한다.
- DataParallel: 단순히 데이터를 분배한 후 평균을 취한다
- GPU 사용 불균형 문제 발생, Batch 사이즈 감소(한 GPU가 병목), GIL
- DistributedDataParallel: 각 CPU마다 process 생성하여 개별 GPU에 할당한다
- 기본적으로 DataParallel로 하나 개별적으로 연산의 평균을 낸다, 멀티프로세싱 통신 규약 및 DataLoader sampler 정의 필요
하이퍼 파라미터 튜닝은 기본적으로 grid하거나 random한 방법이 사용된다.
- 최근에는 베이지안 기반 기법들잊 주도(BOHB 등)
튜닝을 위해 multi-node multi preocessing을 지원하는 모듈인 Ray가 있다.
- ML/DL의 병렬 처리를 위해 개발된 모듈
- 기본적으로 현재의 분산병렬 ML/DL 모듈의 표준
- Hyperparameter Search를 위한 다양한 모듈 제공
Trouble Shooting
GPU 사용 시 여러가 문제가 발생할 수 있다.
- OOM: Out of memory
- CUDNN_STATUS_NOT_INIT
- device-side-assert 등
GPUtil을 사용하여 GPU 상태를 확인할 수 있다.
- nvdia-smi처럼 GPU의 상태를 보여주는 모듈
- Colab은 환경에서 GPU 상태를 보여주기 편하다
- iter 마다 메모리가 늘어나는지 확인한다
import torch
from GPUtill import showUtilization as gpu_usage
torch.cuda.empty_cache()를 사용하여 사용되지 않은 GPU상 cache를 정리할 수 있다.
- 가용 메모리를 확보
- del과는 구분이 필요
- reset 대신 쓰기 좋은 함수
학습 loop에 tensor로 축적되는 변수를 확인할 수도 있다.
- tensor로 처리된 변수는 GPU상에 메모리 사용
- 해당 변수 loop 안에 연산에 있을 때 GPU에 computational graph를 생성 (메모리 잠식)
- 1-d tensor의 경우 python 기본 객체로 변환하여 처리한다
del 명령어를 적절히 사용할 수 도 있다.
- 필요가 없어진 변수는 적절한 삭제가 필요하다
- python의 메모리 배치 특성상 loop이 끝나도 메모리를 차지한다
Inference 시점에서는 torch.no_grad() 구문을 사용하여 메모리 buffer 현상을 방지할 수 있다.
- backward pass로 인해 쌓이는 메모리에서 자유롭다