공통 · 하드웨어 · 2026-09-18
DP: 모델을 복제해 입력 나누기
같은 모델을 여러 GPU에 복제해 입력을 나누고, 추론의 요청 분산과 학습의 기울기 동기화가 다른 이유를 설명합니다.
GPU를 늘렸을 때 가장 먼저 생각할 수 있는 방법은 같은 모델을 여러 벌 준비하는 것입니다. 여러 사람이 같은 도구를 하나씩 가지고 서로 다른 일을 처리하는 모습과 비슷합니다. 이 방식이 데이터 병렬화(Data Parallelism, DP)입니다.
이 글에서는 모델과 입력의 배치를 먼저 보고, 가중치를 고정한 추론과 가중치를 바꾸는 학습에서 무엇이 달라지는지 살펴보겠습니다. 마지막에는 입력을 나누는 방식이 추론의 요청 처리량과 학습의 데이터 처리량을 어떻게 높이는지 살펴보겠습니다. 예시는 입력 토큰마다 같은 가중치 집합을 사용하는 일반적인 dense 모델을 기준으로 합니다.
모델은 복제하고 입력은 나누기
GPU 네 개가 각각 동일한 모델 W 전체를 보관한다고 하겠습니다. 요청 A를 GPU 0에, B를 GPU 1에 보내는 식으로 입력을 배분합니다. 각 GPU는 자기 요청을 모델의 처음부터 끝까지 계산합니다.
나누는 것은 모델의 층이나 가중치 조각이 아니라 각 복제본이 처리할 입력입니다. 따라서 기본 DP만으로는 GPU당 가중치 메모리가 줄어들지 않습니다. 모델 한 벌이 한 GPU에 들어가지 않는 문제는 이 배치로 해결되지 않습니다.
반면 모델이 들어가고 요청이 충분하면 여러 GPU를 동시에 사용할 수 있습니다. 한 GPU가 하나의 요청만 처리해야 한다는 뜻은 아닙니다. 각 복제본 안에서도 여러 입력을 묶어 계산할 수 있으며, 그 묶음의 크기와 배분 방법에 따라 실제 처리량은 달라집니다.
추론에서는 요청을 나누어 처리하기
추론은 준비된 가중치로 입력의 결과를 계산하는 과정입니다. 가중치를 고정하고 서로 독립적인 요청을 처리한다면, 각 복제본이 매번 계산 결과를 All-Reduce할 필요는 없습니다. 요청 A의 결과를 만들기 위해 요청 B의 결과가 필요하지 않기 때문입니다.
대신 요청을 어느 복제본에 보낼지 정하는 분산기가 필요합니다. 단순히 차례대로 배분할 수도 있지만 입력 길이와 출력 길이가 다르면 같은 요청 수가 같은 작업량을 뜻하지 않습니다. 이미 많은 일을 맡은 GPU에 긴 요청이 더 몰리면 대기가 길어질 수 있습니다.
또한 한 요청이 여러 번의 계산으로 이어지면 그 요청에 필요한 상태도 관리해야 합니다. 예를 들어 토큰을 하나씩 생성하는 요청은 앞서 계산한 정보를 재사용할 수 있으므로, 다음 계산을 아무 복제본에나 보내는 것만으로는 충분하지 않습니다. 상태를 유지하거나 옮기는 방식까지 맞춰야 합니다. 이런 요청 분산의 실제 사례는 vLLM의 데이터 병렬 배포 설명에서 볼 수 있습니다. 이 글의 독립 dense 복제본과 달리 MoE를 포함한 구성은 추가적인 통신 관계를 가질 수 있습니다.
학습에서는 기울기를 함께 반영하기
학습은 입력에 대한 예측을 평가한 뒤 모델 가중치를 바꾸는 과정입니다. 기울기는 손실을 줄이기 위해 각 가중치를 어느 방향으로 얼마나 바꿀지 계산하는 데 쓰이는 값입니다. 같은 모델로 시작하더라도 서로 다른 입력을 보면 기울기가 달라집니다.
각 GPU가 자기 기울기만 반영하면 모델 복제본들이 서로 달라집니다. 하나의 모델을 함께 학습하려면 입력별 기여를 모아 같은 갱신을 수행해야 합니다. 같은 크기의 입력 묶음에서 구한 평균 기울기를 다시 참여자 사이에서 평균내는 예를 보겠습니다.
그림은 가중치 하나를 10으로 두고, 두 GPU가 기울기 2와 6을 계산한 예입니다. All-Reduce로 합산한 뒤 2로 나누면 두 GPU가 모두 평균 4를 얻습니다. 학습률을 0.1로 두고 기울기에 비례해 빼는 단순한 SGD 갱신을 적용하면 모두 9.6이 됩니다. SGD는 이러한 가중치 갱신 방법의 하나입니다.
PyTorch DDP는 복제본 사이의 기울기 동기화를 제공합니다. 실제로는 여러 기울기를 묶거나 계산 중 준비된 것부터 통신할 수 있습니다. 그림처럼 모든 계산이 끝난 뒤 반드시 단 한 번만 통신한다는 뜻은 아닙니다. 입력 묶음의 크기나 손실의 합산·평균 방식이 달라지면 기울기를 합치는 비중과 나눗셈도 다시 확인해야 합니다.
입력을 나누어 처리량 높이기
DP는 서로 다른 입력을 여러 복제본에 나누어, 같은 시간에 더 많은 일을 처리하는 방법입니다. 추론에서는 완료하는 요청 수로, 학습에서는 처리하는 데이터 양으로 그 효과를 살펴볼 수 있습니다. 이처럼 일정 시간 동안 처리한 작업량을 처리량이라고 합니다.
추론에서는 각 복제본이 서로 다른 요청을 맡습니다. 아래는 네 요청이 동시에 도착하고 각 요청의 계산에 같은 시간이 걸리는 예입니다.
GPU 하나는 네 요청을 네 칸에, GPU 두 개는 두 칸에 마칩니다. 여러 요청을 끝내는 시간은 줄었지만, 각 요청의 계산은 여전히 한 칸입니다. 한 요청의 계산을 나누지는 않았기 때문입니다. 다만 사용자가 경험하는 응답 시간에는 계산 전의 대기도 포함되므로, 뒤의 요청이 더 일찍 시작하면 응답 시간도 줄어들 수 있습니다.
학습에서는 각 복제본이 서로 다른 학습 데이터를 계산하고, 그 기울기를 모아 가중치를 갱신합니다. 예를 들어 GPU 하나가 입력 8개를 처리한 뒤 갱신하던 작업을 생각해 보겠습니다. GPU 두 개가 각각 8개씩 처리하고 기울기를 합치면, 한 번의 갱신에 총 16개의 입력을 반영할 수 있습니다. GPU마다 맡는 양을 유지하면서 한 번에 학습하는 전체 데이터 양을 늘리는 방식입니다. 이 예에서 한 번의 갱신에 사용하는 전체 입력 묶음의 크기를 전체 배치 크기라고 합니다.
전체 배치를 반드시 키워야 하는 것은 아닙니다. 전체 입력을 8개로 유지하고 두 GPU가 4개씩 나누어 계산할 수도 있습니다. 이 경우에는 같은 양의 계산을 더 빨리 마치는 것을 기대합니다. 반대로 전체 배치를 키우는 경우에는 갱신마다 사용하는 데이터 양도 달라지므로, 데이터 처리량이 늘었다고 목표 모델 성능에 도달하는 시간까지 같은 비율로 줄어든다고 볼 수는 없습니다.
두 경우 모두 GPU 수만큼 처리량이 늘어나는 것은 아닙니다. 입력이 적으면 GPU가 쉴 수 있고, GPU마다 맡는 묶음이 작아지면 계산 효율이 낮아질 수도 있습니다. 학습에서는 가장 느린 참여자의 기울기를 기다리는 시간과 동기화 비용도 중요합니다. 따라서 DP의 효과는 추론에서는 요청 처리량과 응답 시간으로, 학습에서는 데이터 처리량과 전체 배치 크기를 함께 보며 판단해야 합니다.
모델을 복제하기 어려울 만큼 크거나 같은 입력의 계산을 나누고 싶다면 다른 배치가 필요합니다. TP: 하나의 연산을 여러 GPU로 나누기에서는 하나의 행렬 곱을 나누면서 생기는 통신을 살펴보겠습니다.


