딥러닝의 학습 파이프라인은 크게 두 가지로 구성된다.
- 데이터 (CPU)
- 티스크에서 데이터 읽기
- 전처리
- batch 만들기
- 학습 (GPU)
- forward
- loss
- back propagation
딥러닝 학습 파이프라인을 최적화한다 하면(GPU-util을 99% 찍는다고 하면) 두 가지 모두를 최적화해야 한다. 그래야 비로소 GPU가 최적의 상태로 일을 하게 된다.
1. 데이터가 GPU에 올라가는 과정
- 데이터를 읽으라는 명령을 받는다 (user mode)
- user mode > kernel mode (context switching)
- kernel mode에서 file system I/O에 디스크에 있는 해당 데이터를 return해달라고 명령
- return받은 데이터를 메모리에 올림 (kernel mode > user mode)
- 메모리에 있는 데이터를 GPU에 올림
여기서
- 사용하고자 하는 데이터 전부가 메모리에 올라가는 경우 (작은 경우)
- 사용하고자 하는 데이터 전부가 메모리에 올라가지 못하는 경우 (큰 경우)
로 나뉜다.
디스크에서 메모리로 데이터를 올리는 작업이 상대적으로 매우 느려 병목이 일어날 확률이 높다는 것을 의미한다.
2. 모델이 학습되는 과정
한 batch는 1, 2, 3의 과정을 거쳐 학습하게 된다.
- disk → memory 로 데이터를 올리는 과정
- CPU가 memory에 올라간 데이터를 전처리, batch를 만드는 과정
- GPU가 한 batch를 학습하는 과정 (weight update)
위 파이프라인대로 학습을 하게되면 무조건 GPU util이 100%가 되지 못한다.
GPU가 한 batch 학습을 끝내고 다음 batch 학습하기 전까지 1+2 시간 동안 지연이 되기 때문이다.
데이터 파이프라인을 최적화하는 방법들
1. Multi process data loading
CPU0가 한 batch를 GPU에 올려 학습하는 동안 다른 CPU1이 다음 batch를 준비한다.
이렇게 되면 GPU는 시간의 지연 없이 바로 다음 batch를 학습할 수 있기 때문에 지연이 일어나지 않는다. (=prefetch)
from torch.utils.data.dataloader import DataLoader
train_loader = DataLoader(dataset=train_set,
num_workers=4, # 사용할 Process의 수
batch_size=512,
persistent_workers=True)
num_workers를 컴퓨터 상황에 맞게 늘려주면 된다
2. 크기가 작은 datatype 사용하기
torch의 경우 모델 parameter가 float32 type이므로 input 또한 float32가 되어야 한다.
이는 uint8보다 4배 더 큰 크기이므로 데이터를 전송할 때 4배만큼 시간이 더 걸린다.
따라서 실제 모델에 넣기 전에는 크기가 작은 datatype으로 갖고 있다가 모델에 넣어주기 직전에 normalize하여 float32로 바꿔주는 것이 더 빠르다.
3. chunk hit
HDF5(Hierarchical Data Format 5)는 HDF 그룹에 의해 관리되고 있는 대용량의 데이터를 저장하기 위한 파일 형식이다.
계층적으로 구조화된 배열 데이터를 저장하기에 용이하다.
다차원의 dataset을 연속적인 file에 mapping시키는 방법
- contiguous layout
- dataset을 일자로 편다
- 배열의 메모리에 저장되는 방식과 유사하다
- 한 개의 통으로 디스크에 저장된다
- chunk layout
- dataset을 여러 개의 chunk로 나누어서 저장한다
- 파일 안에 한 블록이 무작위로 저장된다
- chunk 별로 읽고 쓸 수 있다
import h5py
celebA = h5py.File(DATA_DIR, 'w', rdcc_nslots=11213, rdcc_nbytes=1024**3, rdcc_w0=1)
celebA.create_dataset('images',
data=batch_images,
dtype=np.uint8,
chunks=(100, 3, 217, 178), # 11 MB : Chunk Size
maxshape=(None, 3, 218, 178))
celebA.create_dataset('labels',
data=labels_h5[:size],
dtype=np.uint8,
chunks=(20000,))
chunk에 있는 데이터 하나를 참조하면 해당 chunk 전체가 메모리에 올라간다.
이후 임의의 데이터를 참조했을 때, 해당 데이터가 메모리에 올라가 있는 chunk에 있으면 메모리에서 바로 참조한다.
4. batch echoing
GPU에 올라온 한 batch를 여러 번 사용하는 것을 의미한다.
장점) 학습의 속도를 증가시킬 수 있다
단점) randomness가 감소한다
GPU Util 99% 달성하기
딥러닝 공부를 하다 보면 반드시 보게 되는 하나의 창이 있는데.. 바로 nvidia-smi 했을 때 나오는 GPU의 상태를 보여주는 창이다. 오른쪽에 보면 GPU-Util이라는 수치가 있는데, 이는 GPU가 얼마나 가용
ainote.tistory.com
'DL_general' 카테고리의 다른 글
XGBoost (1) | 2023.03.15 |
---|---|
localization (0) | 2023.03.15 |
YOLO (0) | 2023.03.13 |
cosine similarity (0) | 2023.03.08 |
auto encoder (0) | 2023.03.07 |