URL: https://www.youtube.com/watch?v=tNAV259UhCM 날짜: 2026-10-10 채널: aiDotEngineer (AI Engineer) 발표자: Tarun Sunkaraneni (Amazon AGI) 재생 시간: 17분 1초 원문 제목: From 15% to 90% GPU Utilization: Fix the Data Pipeline, Not the Model
📌 핵심 질문 / 이 다이제스트가 다루는 핵심 논점
==멀티모달 학습에서 낮은 GPU 활용률의 원인은 모델이나 커널이 아니라 데이터를 제때 준비·전달하지 못하는 파이프라인일 가능성이 크다.== 데이터 로딩·변환·전송을 프로파일링하고 병목에 맞춰 동시성(concurrency), 프리페칭(prefetching), Ray object store 기반 zero-copy, 분산 스케줄링을 차례로 적용하면 GPU 활용률을 15%에서 90%까지 끌어올릴 수 있다.
- Qwen3-VL 계열 멀티모달 SFT의 기준 파이프라인은 GPU가 계산하는 15~20초보다 S3 데이터 수집에 100초 이상을 썼다.
- 이미지 가져오기와 전처리를 비동기 I/O 및 Ray actor로 병렬화하자 약 25% 속도가 개선됐고, 프리페칭으로 배치별 대기 시간이 거의 0초가 됐다.
- 멀티모달 텐서를 프로세스 사이에서 반복 복사하는 문제는 Ray object store의 객체 참조(object reference)와 직접 검색으로 줄였다.
- 규모를 키우자 한 노드의 네트워크 인터페이스 카드(NIC)가 새 병목이 됐고, worker 분산 배치와 zero-copy retrieval을 함께 적용해 추가 처리량 50%를 확보했다.
GPU를 최대한 바쁘게 만드는 것이 최종 목적이 아니다. 데이터가 병목이 되지 않는 안정적인 파이프라인을 만들고, 파이프라인의 각 단계가 CPU-bound인지, I/O-bound인지, GPU-bound인지 계속 다시 확인하는 것이 목적이다.
1. 멀티모달 학습의 진짜 병목을 정의하기
멀티모달 SFT의 처리량은 GPU 연산 속도만으로 결정되지 않고, GPU에 입력이 도착하기 전의 준비 과정 전체에 좌우된다.
1.1. GPU 의존성에 대한 질문
-
학습 루프가 실제로 GPU에 막혀 있는지 확인한다
- 모델의 커널(kernel)을 최적화하는 논의가 많지만, 멀티모달 처리량의 가장 어려운 부분은 커널 자체가 아닐 수 있다.
- GPU가 계속 계산하도록 데이터를 끊임없이 공급하는 일이 먼저 해결되어야 한다.
- GPU가 비어 있는 순간이 모델이 느려서인지, 데이터가 도착하지 않아서인지 구분해야 한다.
-
기준 파이프라인을 만든 뒤 병목을 하나씩 제거한다
- 먼저 멀티모달 학습 파이프라인의 기준선을 측정한다.
- 관찰된 병목을 한 번에 하나씩 해결해야 각 최적화가 실제로 무엇을 개선했는지 알 수 있다.
- 최적화 순서는 이미지 하나를 처리하는 동시성, 필요한 시점보다 먼저 데이터를 준비하는 프리페칭, 프로세스 사이의 복사 최소화, 프레임워크 설정 조정으로 구성된다.
1.2. 멀티모달 전처리가 CPU-heavy인 이유
-
이미지·오디오·비디오마다 GPU 이전 단계가 존재한다
- 이미지는 로딩(loading), 크기 조정(resizing), 정규화(normalizing)를 수행하며 Pillow(PIL) 같은 라이브러리를 사용할 수 있다.
- 오디오는 로딩과 크로핑(cropping)이 필요하고 NumPy 배열을 사용할 수 있다.
- 비디오는 이미지와 오디오 처리의 조합에 가까운 여러 전처리 단계를 가진다.
-
CPU가 더 많은데도 GPU가 굶는 역설이 생긴다
- 학습 클러스터에는 보통 GPU보다 CPU가 더 많이 배치돼 있다.
- 그럼에도 순차적인 데이터 파이프라인에서는 CPU가 데이터를 충분히 빨리 준비하지 못해 GPU가 굶는다.
- 따라서 GPU가 비어 있다는 사실만 보고 모델이나 GPU 커널부터 바꾸면 실제 원인을 놓칠 수 있다.
1.3. 대기 시간 비율(wait-time ratio)
-
비율의 정의
- 분자는 데이터를 준비하고 GPU로 전송하는 데 걸리는 시간이다.
- 분모는 데이터 준비·전송 시간과 실제 학습 시간이 합쳐진 전체 파이프라인 시간이다.
- 식으로 표현하면
wait-time ratio = (data preparation time + transfer time) / total pipeline time이다.
-
목표 수치와 해석
- 기준선에서 GPU 활용률은 15%였고, 시간의 85%가 데이터 획득에 묶여 있었다.
- 최적화 후 대기 시간은 10% 미만 수준까지 내려가며 GPU 활용률은 90%에 도달했다.
- 목표는 GPU 활용률 자체가 아니라 wait-time ratio를 낮춰 데이터가 절대 병목이 되지 않도록 하는 것이다.
2. 학습 스택과 데이터 흐름
Qwen3-VL 계열 모델을 Chat VQA와 멀티턴 VLM 대화 데이터로 학습시키는 상황에서, GPU 계산 전에 데이터가 세 단계를 통과한다.
2.1. 사용한 모델과 학습 형태
-
멀티모달 SFT 구성
- Qwen3-VL 기반 모델을 사용한다.
- Chat VQA와 멀티턴 VLM conversation 패러다임의 데이터를 학습한다.
- 텍스트 토큰뿐 아니라 이미지에서 나온 vision token과 이미지 텐서가 함께 전달된다.
-
GPU 이전의 필수 단계
- 데이터를 저장소에서 로드(load)한다.
- 이미지·텍스트를 모델 입력 형식으로 변환(transform)한다.
- 변환된 데이터를 GPU로 운반(transport)한다.
- 세 단계 중 어느 하나라도 늦으면 GPU는 다음 배치를 기다리며 유휴 상태가 된다.
2.2. 데이터 형식과 저장소
-
JSONL과 상대 이미지 경로
- 샘플은 JSONL 파일로 저장한다.
- 각 이미지 경로는 해당 예제가 있는 위치를 기준으로 상대적으로 연결된다.
- 예시로
image 33471.jpeg라는 이미지가 있으며, 화면상 파란 버스처럼 보이는 사진으로 제시된다.
-
S3 기반 원격 데이터
- 이미지 데이터는 S3에 저장되어 있다고 가정한다.
- 따라서 각 배치마다 원격 객체 저장소에서 이미지 바이트를 가져오는 네트워크 I/O가 발생한다.
- S3 접근이 순차적으로 이뤄지면 이미지 디코딩·전처리보다 네트워크 대기 시간이 훨씬 커질 수 있다.
2.3. 시스템 레이아웃
-
Data generator의 책임
- 왼쪽의 data generator가 데이터 로딩, 데이터 변환, 데이터 전송을 모두 담당한다.
- 준비된 데이터는 Megatron의 data-parallel(DP) rank들로 fan-out된다.
- 한 곳에서 모든 준비 작업을 맡기 때문에 data generator와 worker pool의 배치가 네트워크 병목에 직접 영향을 준다.
-
Megatron DP rank의 책임
- 각 병렬 rank는 coordinator가 결정한 데이터 파티션을 받는다.
- rank는 배치를 collate하고 forward pass와 backward pass를 수행한다.
- Megatron은 DP rank 사이에서 모델 weight를 최적화하는 역할을 맡으며, 해당 부분은 내부 동작을 더 파고들지 않는 블랙박스로 둔다.
3. 기준선: 순차 처리로 발생한 GPU 활용률 15%
기준선은 단순하지만, 데이터의 모든 작업을 샘플별·순서대로 수행하기 때문에 GPU가 대부분의 시간을 기다린다.
3.1. 샘플 하나를 처리하는 순차 경로
-
한 샘플의 처리 순서
- 객체 저장소에서 이미지를 가져온다.
- 텍스트를 토크나이즈(tokenize)한다.
- 이미지를 resize하고 normalize한다.
- 변환된 이미지와 텍스트를 모델에 전달한다.
-
배치 전체가 직렬화된다
- 프로파일링에서 빨간색으로 표시된 단계는 이미지를 하나씩 가져오고 하나씩 처리하는 직렬(serial) 작업이다.
- trainer가 배치 크기 256을 요청하면 256개 이미지를 모두 순서대로 처리한 다음에야 배치를 모델에 넣을 수 있다.
- 샘플끼리 의존성이 없는데도 처리 순서가 불필요하게 고정돼 있다.
3.2. 기준선 프로파일링 결과
-
학습 시간과 데이터 시간의 불균형
- 실제 학습 자체는 약 15~20초 걸린다.
- 데이터를 가져오는 시간은 100초를 넘는다.
- 결과적으로 GPU 활용률은 15%에 그친다.
-
Flame graph가 보여주는 원인
- 프로파일링 flame graph의 대부분은 S3 load가 차지한다.
- 뒤쪽에는 Pillow 라이브러리로 실제 이미지를 로드하는 긴 꼬리 구간이 남는다.
- 모델 계산을 줄이는 것보다 S3 접근과 이미지 로딩 경로를 먼저 바꾸는 것이 효과적이라는 근거가 된다.
4. 해결책 1: 동시성으로 이미지 로딩·변환 병렬화
샘플 사이에 의존성이 없으므로 배치의 독립적인 작업을 worker pool에 분배해 순차 대기를 줄인다.
4.1. 병렬화할 두 가지 비용
-
이미지 획득 비용
- S3에서 이미지 파일을 가져오는 네트워크 I/O가 첫 번째 비용이다.
- 256개 샘플을 요청받았을 때 한 번에 여러 이미지를 가져오면 네트워크 대기 시간을 겹칠 수 있다.
-
이미지·텍스트 처리 비용
- 이미지 디코딩과 vision preprocessing이 두 번째 비용이다.
- 텍스트 토크나이징도 함께 처리해야 한다.
- 각 샘플이 서로 독립적이므로 이 작업은 embarrassingly parallel한 형태다.
4.2. Async, thread, process의 선택 기준
-
비동기 프로그래밍(async programming)
- SQL query나 네트워크 request처럼 I/O 중심인 작업에 적합하다.
- 이미지 가져오기를 기다리는 동안 다른 요청을 진행해 대기 시간을 겹칠 수 있다.
-
Thread
- Python의 global interpreter lock(GIL)을 해제하는 CPU 작업에 활용할 수 있다.
- 어떤 연산이 실제로 GIL을 놓는지는 명확하지 않으므로 사용 라이브러리별 조사가 필요하다.
- Hugging Face Transformers tokenizer, Pillow transforms API, 일부 Pandas 연산이 흔한 후보로 언급된다.
-
Process
- 프로세스는 더 무겁지만 작업 사이에 완전한 격리를 제공한다.
- 여러 CPU 코어를 활용할 수 있으므로 GIL의 영향을 피할 수 있다.
- 어떤 동시성 도구가 익숙한지가 아니라 실제 병목의 종류에 맞춰 선택해야 한다.
4.3. Async I/O + Ray actors 적용 결과
-
선택한 조합
- 이미지 fetch에는 async I/O를 사용한다.
- 처리 worker에는 Ray actors를 process multiprocessing 라이브러리처럼 사용한다.
- Ray actor는 일반 process와 비슷하면서 worker 사이 통신 API를 제공하므로 별도의 통신 계층을 직접 만들 필요가 줄어든다.
-
측정 결과와 한계
- 전체 처리는 가장 느린 링크(slowest link)만큼 느리므로 한 단계만 빠르게 만들어서는 충분하지 않다.
- 배치별 데이터 fetch 시간은 약 40초 수준으로 내려갔다.
- 순차 기준선 대비 약 25% 속도 향상을 얻었지만, 여러 학습 step을 진행하면 worker pool이 trainer 요청을 기다리는 큰 간격이 다시 나타났다.
5. 해결책 2: 프리페칭으로 trainer보다 producer를 앞세우기
trainer가 데이터를 요청한 뒤에 준비를 시작하지 않고, background thread가 큐를 미리 채워 요청 시점에 이미 준비된 샘플을 반환한다.
5.1. Producer–consumer 구조
-
백그라운드 큐 채우기
- background thread가 앞선 시점에 데이터를 가져와 queue를 채운다.
- producer가 consumer인 trainer보다 높은 배수로 예제를 생산하도록 한다.
- trainer가 데이터를 요청할 때 실제 fetch나 변환을 기다리지 않고 큐에서 즉시 꺼낸다.
-
대기 구간 제거
- 기존에는 trainer의 요청이 worker pool의 데이터 준비를 시작하는 신호였다.
- 프리페칭은 요청과 준비를 시간상 분리해 producer가 항상 consumer보다 앞서도록 만든다.
- 결과적으로 배치별 데이터 fetch·processing 시간은 거의 0초가 된다.
5.2. 프리페칭의 운영상 주의점
-
Checkpointing과 resumption 복잡성
- model checkpoint와 data loader checkpoint를 큐의 현재 상태와 함께 일관되게 저장·복원해야 한다.
- 큐에 이미 들어간 샘플과 trainer가 소비한 샘플의 위치를 관리해야 하므로 단순한 순차 loader보다 재개가 까다롭다.
-
Cold start
- 학습 초반에는 queue가 채워지는 동안 cold start가 발생한다.
- 큐가 충분히 채워지기 전에는 trainer가 다시 대기할 수 있다.
- 이 초기 구간과 checkpoint 문제를 다루면 producer를 consumer보다 앞세우는 설계가 큰 효과를 낸다.
5.3. 두 번째 해결책 이후의 상태
-
로드·변환 병목 해소
- trainer가 데이터를 요청하기 훨씬 전에 fetch와 processing이 끝난다.
- 데이터 로드 병목과 변환 병목을 효과적으로 해결한다.
- GPU에는 throughput이 충분히 공급되는 것처럼 보였지만, 데이터 전송 비용은 여전히 남아 있었다.
-
새 병목의 노출
- 두 해결책을 적용한 뒤에는 데이터 transport cost가 오히려 커졌다.
- 파이프라인 한 병목을 해결하면 이전에는 가려져 있던 다음 병목이 드러난다는 패턴이 확인된다.
6. 해결책 3: Ray object store로 불필요한 복사 제거
멀티모달 샘플은 수 MB에 이르는 큰 이미지 배열을 포함하므로, 프로세스 사이에서 값을 반복 전달하면 데이터 generator가 전송 자체로 막힌다.
6.1. 반복 복사가 발생하는 이유
-
프로세스 경계를 넘는 값 전달
- 기본 동작에서 각 샘플은 값(value)으로 반환된다.
- worker에서 샘플을 pickle한다.
- coordinator로 배열을 복사한다.
- trainer로 보내기 위해 다시 pickle한다.
- 샘플마다, 매 step마다 아무도 요청하지 않은 memory copy가 반복된다.
-
멀티모달 텐서의 크기
- 멀티모달 텐서는 샘플 하나당 메가바이트 단위일 수 있다.
- 샘플 수와 DP rank 수가 늘면 복사 비용도 함께 늘어난다.
- 프리페칭으로 준비 시간을 없애도 복사 경로가 남아 있으면 data generator가 포화될 수 있다.
6.2. Object reference 기반 전달
-
Ray object store의 구조
- 각 샘플 대신 데이터가 있는 위치를 가리키는 object reference를 전달한다.
- driver는 큰 텐서 자체가 아니라 포인터(pointer)를 보유한다.
- 텐서는 head node를 거쳐 왕복하지 않는다.
-
DP rank의 직접 검색
- Megatron DP rank가 필요한 시점에 Ray store에서 텐서를 직접 가져온다.
- worker→coordinator→trainer로 값 전체를 반복 복사하는 경로를 피한다.
- 프리페처가 별도로 수행하던 불필요한 object put 호출도 제거된다.
6.3. 통신 비용을 포함한 설계
-
병렬성의 대가
- 동시성이나 병렬성을 늘릴 때는 계산량 감소뿐 아니라 worker 사이의 추가 통신을 함께 계산해야 한다.
- 새로운 병렬화 레이어가 오히려 큰 객체의 복사를 추가하면 개선 효과가 사라질 수 있다.
- 병렬화 선택마다 데이터가 실제로 어디에 존재하고 누가 직접 읽는지 설계해야 한다.
-
측정 결과
- Ray store 적용으로 communication cost가 내려갔다.
- 데이터를 기다리는 시간의 비율도 함께 감소했다.
- 직렬 기준선, 동시성, 프리페칭, object store를 순서대로 적용해 wait-time ratio를 85%에서 20%로 낮췄다.
- 상단 그래프에서 반복적으로 나타나던 톱니(saw-tooth) 패턴도 크게 완화돼 GPU 활용률이 상승했다.
7. 규모 확장 때 드러난 네트워크 병목
작은 실험에서 좋아 보이던 파이프라인을 production 규모로 확장하자, 설정값만 키웠는데도 wait-time ratio가 다시 증가했다.
7.1. 확장 조건과 결과
-
늘린 규모
- data-parallel rank를 네 배로 늘렸다.
- data stream을 200개로 늘렸다.
- batch size도 네 배(x4)로 키웠다.
-
새로운 대기 시간
- 같은 파이프라인인데 wait-time ratio가 다시 올라갔다.
- 동시성, 프리페칭, object store가 틀린 것이 아니라 데이터가 집중되는 위치가 새 병목이 됐다.
- 작은 규모에서 드러나지 않던 단일 노드 네트워크 한계가 전체 처리량을 제한했다.
7.2. NIC 포화와 Ray의 기본 배치 정책
-
한 노드로 집중되는 작업
- 빠른 데이터 전송을 위해 data generator와 worker pool을 같은 노드에 배치(co-locate)했다.
- 이미지 fetching·processing·storing이 특정 노드에 몰렸다.
- 해당 노드의 network interface card(NIC) 처리량이 학습 파이프라인의 수요를 따라가지 못했다.
-
Ray의 기본 스케줄링 효과
- Ray는 기본적으로 worker를 같은 노드에 배치하는 것을 선호한다.
- 한 머신을 먼저 병목시킨 뒤에야 다른 머신으로 확장되므로 전체 클러스터 자원이 균등하게 사용되지 않을 수 있다.
- 계산을 빠르게 하려던 co-location이 네트워크 대역폭 집중이라는 반대 비용을 만들었다.
7.3. Worker 분산과 두 가지 플래그
-
Disaggregation
- 전체 처리 과정을 여러 노드에 분산해 worker가 각자 이미지 처리와 저장을 수행하도록 한다.
- DP rank가 필요한 시점에 lazy·just-in-time 방식으로 데이터를 가져오게 한다.
- 한 노드의 NIC가 모든 데이터 수요를 감당하지 않아도 된다.
-
조정한 설정
- 첫 번째는 zero-copy retrieval이다.
- 두 번째는 spread scheduling mechanism이다.
- 작은 규모에서는 두 설정 중 어느 것도 뚜렷한 개선을 보이지 않았다.
- 큰 규모에서는 두 설정이 시너지를 내며 데이터 처리 속도를 크게 높였다.
7.4. Scale-dependent configuration
-
작은 실험만으로 설정을 버리면 안 된다
- 어떤 설정은 small-scale 실험에서 성능을 높이지 못할 수 있다.
- 같은 설정이 larger-scale 실험에서는 네트워크 분산과 객체 접근 패턴 때문에 결정적인 효과를 낼 수 있다.
- scaling ladder의 각 단계에서 ablation을 수행해 설정의 효과를 확인해야 한다.
-
최종 파이프라인과 효과
- 최종 시스템은 concurrent하고 eager한 데이터 접근 패턴을 가진다.
- 부하를 학습 과정 전반에 고르게 공유해 GPU가 따뜻한 상태를 유지하고 학습이 매끄럽고 안정적으로 진행되도록 한다.
- zero-copy retrieval과 spread scheduling 두 플래그만으로 확장 환경에서 추가 처리량 50%를 얻었다.
- 같은 knob도 어떤 병목을 마주하느냐에 따라 효과의 방향과 크기가 달라진다.
8. 최종 교훈과 적용 절차
GPU가 비싸다는 사실은 중요하지만, 가장 큰 성능 싸움은 GPU 바깥에서 벌어질 수 있다.
8.1. 먼저 병목의 종류를 분류한다
-
CPU-bound와 GPU-bound를 구분한다
- CPU가 데이터 준비를 못 따라가는지 GPU 계산이 느린지 프로파일링으로 확인한다.
- GPU 활용률이 낮다는 표면 증상만으로 GPU나 모델을 바꾸지 않는다.
-
I/O-bound와 compute-bound를 구분한다
- S3 fetch, 이미지 decode, 파일 로딩, 프로세스 간 transport가 시간을 차지하는지 본다.
- 계산이 아니라 I/O가 원인이라면 async I/O와 prefetching이 우선이다.
- CPU 전처리라면 GIL 해제 여부를 확인한 뒤 thread 또는 process를 선택한다.
8.2. 한 병목을 해결하면 다음 병목을 다시 측정한다
-
병목의 연쇄 변화
- 처음에는 전체 throughput이 문제였다.
- 동시성 이후에는 wait time이 핵심 문제가 됐다.
- 프리페칭 이후에는 메모리와 프로세스 간 복사가 드러났다.
- object store 이후에는 retrieval cost와 노드 NIC가 새 제약이 됐다.
-
최적화 순서를 고정된 처방으로 받아들이지 않는다
- parallelism과 prefetching은 고전적이고 유용한 기법이지만 항상 마지막 해답은 아니다.
- Ray 같은 프레임워크의 스케줄링 의미와 데이터 배치 정책도 성능을 좌우한다.
- 클러스터 규모가 바뀌면 같은 설정의 비용·효과도 바뀐다.
8.3. 프로파일링과 scale ladder ablation
-
기준선을 먼저 보존한다
- 순차 기준선의 학습 시간, 데이터 대기 시간, 통신량, GPU utilization을 기록한다.
- 각 변경 뒤 동일한 지표를 다시 측정해 실제 개선을 확인한다.
-
규모별 실험을 반복한다
- 작은 규모에서 효과가 없다는 이유로 zero-copy retrieval이나 spread scheduling을 즉시 제거하지 않는다.
- data-parallel rank, stream 수, batch size를 단계적으로 늘리며 네트워크와 메모리 병목이 어디서 생기는지 확인한다.
- 최적 설정은 하나의 절대값이 아니라 병목과 규모에 맞춰 결정되는 조건부 결과다.
주요 발언 모음
“멀티모달 학습 처리량을 최적화할 때 가장 어려운 부분은 반드시 커널 최적화가 아니다. GPU에 데이터가 계속 공급되도록 만드는 일이다.”
“GPU가 목표가 아니다. 데이터가 절대 병목이 되지 않도록 만드는 것이 목표다.”
“가장 중요한 것은 우리에게 효과가 있었던 도구를 단순히 반복하는 것이 아니라, 병목에 맞는 도구를 선택하는 일이다.”
“GPU는 비싸지만, 때로 가장 큰 싸움은 GPU 바깥에서 벌어진다.”
“한 병목을 해결하면 다른 병목이 드러나는 경우가 많다.”
“작은 규모에서 잘 작동하지 않는 설정이 더 큰 규모에서는 매우 잘 작동할 수 있다.”
핵심 데이터 & 수치
- 기준 GPU 활용률: 순차 데이터 파이프라인에서 15%.
- 기준 학습 시간: 배치 학습 자체는 약 15~20초.
- 기준 데이터 획득 시간: S3에서 데이터를 가져오는 데 100초 이상.
- 기준 wait-time ratio: 전체 시간의 약 85%가 데이터 획득에 묶임.
- 동시성 적용 효과: 배치별 데이터 fetch 시간이 약 40초 수준으로 내려가며 약 25% 속도 향상.
- 프리페칭 효과: 미리 준비된 큐에서 공급해 배치별 데이터 fetch·processing 대기 시간이 거의 0초.
- object store 적용 효과: 반복적인 pickle·메모리 복사를 줄여 communication cost와 wait-time ratio를 낮춤.
- 중간 wait-time ratio: 직렬 기준선 85%에서 20%로 감소.
- 확장 조건: DP rank 4배, data stream 200개, batch size 4배.
- 대규모 환경 추가 처리량: zero-copy retrieval과 spread scheduling을 함께 적용해 50% 증가.
- 최종 GPU 활용률: 데이터 파이프라인 병목을 줄인 결과 약 90%.
핵심 요약 (20줄)
-
멀티모달 학습에서 낮은 GPU 활용률의 원인은 모델보다 데이터 파이프라인일 수 있다.
-
GPU가 계산하는 동안 데이터가 준비되지 않으면 고가의 GPU가 유휴 상태로 남는다.
-
멀티모달 입력은 이미지 로딩과 변환 때문에 텍스트 전용 학습보다 CPU 작업이 많다.
-
이미지 로딩과 전송 시간을 전체 파이프라인 시간으로 나눈 값이 wait-time ratio다.
-
기준 파이프라인은 데이터 획득에 전체 시간의 약 85%를 쓰며 GPU 활용률이 15%에 머물렀다.
-
배치 학습에는 15~20초가 걸렸지만 S3에서 데이터를 가져오는 데 100초 이상이 필요했다.
-
배치 안의 샘플은 독립적이므로 이미지 획득과 전처리를 병렬화할 수 있다.
-
네트워크 I/O에는 async programming을, GIL을 놓는 CPU 작업에는 thread를 고려할 수 있다.
-
여러 코어의 격리가 필요하면 더 무거운 process 기반 처리를 선택할 수 있다.
-
async I/O와 Ray actors를 조합하자 기준선보다 약 25% 빠른 처리가 가능해졌다.
-
병렬화 뒤에도 trainer가 다음 데이터를 요청할 때까지 기다리는 간격이 남았다.
-
background thread가 미리 queue를 채우는 prefetching으로 producer를 consumer보다 앞세울 수 있다.
-
prefetching은 배치별 데이터 대기를 거의 0초로 낮추지만 cold start와 checkpoint 복잡성을 만든다.
-
프리페칭 뒤에는 멀티메가바이트 텐서의 프로세스 간 반복 복사가 새로운 병목이 됐다.
-
Ray object store는 텐서 값 대신 object reference를 전달해 불필요한 복사를 줄인다.
-
동시성·프리페칭·object store 적용으로 wait-time ratio가 85%에서 20%로 감소했다.
-
DP rank와 stream 및 batch size를 키우자 한 노드의 NIC가 네트워크 병목이 됐다.
-
Ray의 worker co-location은 작은 규모에서는 빠르지만 큰 규모에서는 특정 노드의 네트워크를 포화시킬 수 있다.
-
zero-copy retrieval과 spread scheduling은 대규모 환경에서 함께 사용할 때 추가 처리량 50%를 만들었다.
-
모든 최적화는 병목과 규모를 기준으로 선택하고 각 단계마다 프로파일링으로 다시 검증해야 한다.
결론 및 시사점
- GPU 활용률이 낮으면 모델을 먼저 바꾸지 말고 데이터 로딩·변환·전송 시간을 분해해 측정한다.
- 샘플 간 의존성이 없다면 async I/O와 worker pool로 원격 fetch와 CPU 전처리를 겹친다.
- trainer가 요청한 뒤 데이터를 준비하는 구조 대신 prefetch queue를 사용해 producer가 앞서가게 만든다.
- 큰 멀티모달 텐서를 값으로 여러 프로세스에 전달하지 말고 object reference와 공유 object store를 사용한다.
- 병렬화로 계산 시간을 줄여도 통신 비용이 늘 수 있으므로 worker·coordinator·trainer 사이의 데이터 경로를 함께 프로파일링한다.
- 규모를 키울 때는 co-location이 NIC 병목을 만들 수 있으므로 worker를 분산하고 spread scheduling을 검증한다.
- zero-copy와 분산 스케줄링 같은 설정은 small-scale 결과만으로 판단하지 말고 production 규모의 scaling ladder에서 ablation한다.
- 병목은 throughput에서 wait time, memory copy, retrieval cost로 계속 이동하므로 최적화마다 전체 파이프라인을 다시 측정한다.
- 최종 목표는 GPU 숫자를 높이는 것이 아니라 데이터가 끊기지 않는 안정적이고 확장 가능한 학습 시스템을 만드는 것이다.
