Data Loading Library (DALI)

위 그림은 CPU와 GPU의 Capacity 차이가 점점 더 심화될 것을 나타내는 그래프입니다.
2010년 기점으로 CPU의 성장곡선은 점점 완만해지는데 GPU의 성장곡선은 1.5배씩 늘어나는 것을 확인할 수 있습니다.
그런데 CPU의 성장곡선에 비해 CPU에서 수행되는 데이터 전처리의 복잡성은 점점 늘어나고 있습니다.

DALI는 CPU에서 GPU로 데이터를 넣어주는 구간이 병목이 될 것이라고 생각하는데요,
그래서 DALI는 일반적으로 CPU 상에서 전과정으로 이루어지고 있는 전처리에서 가능한 연산들을 GPU에서 수행하고자 합니다.

실제로 MXNet과 DALI의 Training throughput을 비교해보았을 때 MXNet은 17.84K DALI는 22.53K인 것을 알 수 있는데요,
위 결과로 Data Feeding 내에서도 병목이 존재할 수 있음을 알 수 있습니다.
DALI 구성
from nvidia.dali import fn
@nvidia.dali.pipeline_def
def rn50_pipeline():
encoded, label = fn.readers.file(file_root=image_dir)
decoded = fn.decoders.image(encoded, ...)
resized = fn.resize(decoded, size=[224, 224])
normalized = fn.crop_mirror_normalize(resized, mean=mean, std=std)
return normalized, label
pipe = rn50_pipeline(batch_size=128, num_threads=4, device_id=0)
pipe.build()
image, labels = pipe.run()
DALI는 아래의 순서로 구성을 할 수 있는데요,
- 우선 파이프라인을 구성하고 (그래프 기반의 구동 방식, 내부 과정을 sequential하게 구성)
- 적절한 인자를 넣어준 pipe 객체를 생성 후
- pipe 객체를 Build한 다음 Run을 하게 되면
일종의 iterator처럼 이미지가 계속 생성됩니다.
GPU offloading

파이프라인 구성중 decoded 과정에서 device를 "mixed"로 설정하면 GPU offloading이 됩니다.
GPU offloading을 하게 되면 위 그림에서 초록색에 해당하는 영역을 GPU가 담당하게 됩니다.
DataLoader

DALI에서는 Pytorch와의 호환을 위해 Dataloader를 대체가능하게 하는 iterator를 제공합니다.
그래서 DALI iterator로 대체했을 때 for문 안에 있는 내부적인 과정은 동일한 것을 알 수 있습니다.
실험 및 결과
실험 환경 및 실험 내용은 아래와 같습니다.
- 102개의 클래스를 가지는 Flower dataset을 활용(클래스당 40 ~ 258장)
- DataLoaindg 비교: 기타 augmentation없이 resizing만 수행(224, 224)
- Training & Inference time 비교: Resnet18 pretrained, FC layer 교체
파이프라인은 아래와 같이 cpu, gpu, mixed 3가지를 정의합니다.
- cpu: cpu환경에서 전처리 수행
- gpu: decode과정은 cpu로 수행, resize이후 과정은 gpu로 수행
- mixed: decode과정부터 cpu, gpu 적절히 사용하는 mixed로 전처리 수행

그래서 DataLoading 시간속도를 비교해봤을 때 DALI(Mixed)가 가장 빠르고 동일한 CPU 환경에서도 PyTorch 보다는 DALI(CPU)가 빠른 것을 확인할 수 있습니다.
이번에는 학습과 추론 속도를 비교해보겠습니다.
강의에서 설명된 코드를 수행했을 때 아래와 같은 결과를 얻을 수가 있는데요,
- 학습 (5 Epoch)
- DALI: 98.17초
- Torch: 237.67초
- 추론
- DALI: 18.58 초
- Torch: 47.29초
학습 및 추론에서 약 2배 이상의 속도 개선이 발생하는 것을 알 수 있습니다.
생각해보기
- PyTorch 및 DALI는 CPU 환경에서 병렬처리로 데이터 로드를 수행할 수 있습니다. 하지만 대게 DALI가 하나의 GPU를 사용할 때 더 나은 성능을 갖게 되는데요, 여러개의 프로세스보다 하나의 GPU의 수행속도가 더 빠른 이유에 대해서 고민해보세요.
참고 자료
comment