본문 바로가기

DL_general

학습 중 GPU를 100% 쓰지 않는 이유, GPU util을 올리려면?

딥러닝의 학습 파이프라인은 크게 두 가지로 구성된다.

  1. 데이터 (CPU)
  • 티스크에서 데이터 읽기
  • 전처리
  • batch 만들기
  1. 학습 (GPU)
  • forward
  • loss
  • back propagation

딥러닝 학습 파이프라인을 최적화한다 하면(GPU-util을 99% 찍는다고 하면) 두 가지 모두를 최적화해야 한다. 그래야 비로소 GPU가 최적의 상태로 일을 하게 된다.

 

1. 데이터가 GPU에 올라가는 과정

  1. 데이터를 읽으라는 명령을 받는다 (user mode)
  2. user mode > kernel mode (context switching)
  3. kernel mode에서 file system I/O에 디스크에 있는 해당 데이터를 return해달라고 명령
  4. return받은 데이터를 메모리에 올림 (kernel mode > user mode)
  5. 메모리에 있는 데이터를 GPU에 올림

여기서

  1. 사용하고자 하는 데이터 전부가 메모리에 올라가는 경우 (작은 경우)
  2. 사용하고자 하는 데이터 전부가 메모리에 올라가지 못하는 경우 (큰 경우)

로 나뉜다.

디스크에서 메모리로 데이터를 올리는 작업이 상대적으로 매우 느려 병목이 일어날 확률이 높다는 것을 의미한다.

 

2. 모델이 학습되는 과정

한 batch는 1, 2, 3의 과정을 거쳐 학습하게 된다.

  1. disk → memory 로 데이터를 올리는 과정
  2. CPU가 memory에 올라간 데이터를 전처리, batch를 만드는 과정
  3. 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시키는 방법

  1. contiguous layout
    1. dataset을 일자로 편다
    2. 배열의 메모리에 저장되는 방식과 유사하다
    3. 한 개의 통으로 디스크에 저장된다
  2. chunk layout
    1. dataset을 여러 개의 chunk로 나누어서 저장한다
    2. 파일 안에 한 블록이 무작위로 저장된다
    3. 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가 감소한다

 

https://ainote.tistory.com/14

 

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