개인의견 : pipeline Parallelism에 관련된 논문을 몇개 봤는데 그 중에서 가장 재밋는 논문인것 같네요. graph의 toplogy-aware Pipeline Parallelism이라는 당연한 개념을 포함하여 효과적인 결과를 내는것 같습니다. 다만 구현에 대한 오버헤드는 쫌 있을꺼같군요
논문 : https://arxiv.org/pdf/2406.17145
아래글은 Scholar GPT와 대화를 나눈 내용입니다.
Q : 논문의 핵심 내용과 강점, 알고리즘 설명, 그리고 한계점
Answer
논문의 강점과 독창적인 지점
이 논문은 Graph Pipeline Parallelism (GPP)이라는 새로운 개념을 제안하여, 기존의 순차 파이프라인 병렬 처리 방식의 한계를 극복하고 DNN 학습의 성능과 확장성을 크게 개선합니다. 주요 강점과 독창적인 점은 다음과 같습니다:
-
병렬 분기 실행: 기존의 순차적 파이프라인 병렬 처리 (Sequential Pipeline Parallelism, SPP)는 모델을 선형적으로 나누어 순차적으로 처리하지만, GPP는 DNN 모델의 비선형적인 그래프 구조를 반영하여 비의존적 연산이 동시에 실행될 수 있도록 합니다. 이를 통해 메모리 요구량을 줄이고 GPU 성능을 최적화합니다【5†source】.
-
그래프 기반 파이프라인 구조 최적화: GPP는 DNN 모델을 DAG(Directed Acyclic Graph) 구조로 나누고, 이를 기반으로 파이프라인 스테이지의 의존성을 설계하여 순차적 실행이 아닌 비선형적 스케줄링을 가능하게 합니다. 이는 기존 SPP의 단점인 메모리 사용량 증가와 비효율적인 병렬 처리의 문제를 해결합니다【5†source】.
-
GraphPipe 시스템: GPP를 기반으로 설계된 GraphPipe 시스템은 각 DNN 스테이지를 자동으로 분할하고 최적의 마이크로배치 스케줄을 구성하여, 학습 속도를 최대화하고 메모리 사용을 줄일 수 있도록 지원합니다. 기존 파이프라인 시스템과 비교해 최대 1.6배의 처리량을 확보하며, 검색 시간도 9-21배 단축됩니다【5†source】.
핵심 알고리즘 과정 예시
GPP의 핵심 알고리즘은 다음과 같은 과정으로 구성됩니다:
-
파이프라인 스테이지 분할: DNN을 입력받아 각 연산의 종속성을 DAG로 파악하여, 가능한 병렬 연산들을 확인한 후 이를 스테이지로 나눕니다. 예를 들어, DNN의 두 독립적 연산 (O1)과 (O2)가 있을 경우, 이들을 독립적인 파이프라인 스테이지 (S1)과 (S2)로 나눠 병렬로 실행합니다.
-
마이크로배치 스케줄링: 스테이지별 마이크로배치 크기를 최적화하여, 메모리 사용을 최소화하면서 각 마이크로배치의 전방 및 후방 연산을 수행할 순서를 결정합니다. 예시로, 배치가 128로 주어지고 (S1)과 (S2)가 병렬 가능할 때, 스케줄러는 각 스테이지에 독립적으로 마이크로배치를 할당하여 GPU 메모리를 효율적으로 사용합니다.
-
동시 실행 관리: 각 스테이지의 전방 연산이 끝나면 곧바로 후방 연산이 시작되며, 병렬 분기는 최대한 동시 실행되도록 스케줄링합니다. 예를 들어, (S1)과 (S2)의 전방 연산이 동시에 완료되면, (S3)에서 필요한 후방 연산이 바로 진행될 수 있도록 조정합니다.
논문의 한계점
이 논문에는 다음과 같은 한계점이 있습니다:
-
복잡한 최적화 문제: GPP의 최적화 과정이 기존 SPP보다 훨씬 복잡하여, 작은 네트워크에서는 그 성능 향상이 미미할 수 있습니다. 또한 그래프 기반 스케줄링의 경우 계산 복잡도가 높아져, 대규모 모델에서만 성능 향상이 두드러집니다【5†source】.
-
특정 하드웨어 요구: GPP와 GraphPipe의 구현 및 성능 개선은 GPU 메모리와 병렬 연산 처리 능력에 크게 의존합니다. 이는 특정 하드웨어 환경에서 최적의 성능을 보장하지 않을 수 있다는 단점이 있습니다【5†source】.
-
멀티 브랜치 모델에 최적화: 이 방법은 여러 병렬 분기가 있는 모델에서 주로 성능이 향상됩니다. 단일 분기 모델이나 작은 크기의 네트워크에서는 그 효과가 제한적일 수 있습니다.
이 논문은 대규모 다중 분기 DNN 학습의 성능을 극대화하는 데 적합하지만, 그 복잡한 최적화 구조로 인해 모든 모델에 적용 가능한 보편적인 해법은 아닙니다.
Q : 파이프라인 스테이지 분할에 관한 질문이 있는데 어떤 연산이 병렬적으로 진행 될 수 있을지 graph예시를 들어서 자세하게 설명해줄 수 있겠니? 그리고 이때 어떠한 이득을 얻을 수 있는지도 함께 설명해줘
Answer:
파이프라인 스테이지 분할에 대한 예시는 DNN의 그래프 구조를 DAG(Directed Acyclic Graph)으로 표현하면서 가능합니다. 여기서 DAG는 각 노드가 연산을 나타내고, 간선이 연산 간의 데이터 의존성을 나타냅니다. GPP(Graph Pipeline Parallelism)를 통해 병렬적 연산을 활용하여 얻을 수 있는 이점을 중심으로 설명하겠습니다.
1. 병렬 연산 가능 예시: DAG 그래프
다음과 같은 예를 생각해 보겠습니다:
O1
/ \
O2 O3
| |
O4 O5
\ /
O6
위 구조에서 각 노드 (O_i)는 특정 연산을 나타내며, 간선은 해당 연산들 사이의 의존성을 나타냅니다.
- 노드 (O1): 입력 데이터를 받아서 초기 처리를 수행합니다.
- 노드 (O2)와 (O3): 서로 독립적인 연산으로, 동시에 수행할 수 있는 연산입니다. 예를 들어, 이미지 데이터를 처리하는 (O2)와 텍스트 데이터를 처리하는 (O3)라면 서로 병렬로 실행될 수 있습니다.
- 노드 (O4)와 (O5): 각각 (O2)와 (O3)의 출력을 받아서 별도의 연산을 수행합니다. 역시 독립적이므로 병렬 처리가 가능합니다.
- 노드 (O6): (O4)와 (O5)의 출력을 결합하는 마지막 연산으로, 두 이전 연산이 완료된 이후에 실행될 수 있습니다.
2. 병렬 연산이 가능한 이유
이 DAG 구조에서는 (O2)와 (O3), (O4)와 (O5)가 서로 독립적이므로 동시에 실행될 수 있습니다. 이러한 병렬성을 활용해 각 노드를 개별적인 파이프라인 스테이지로 분할하여, GPP는 다음과 같은 스케줄을 구성할 수 있습니다:
- Stage 1: (O1) (초기 입력 처리)
- Stage 2: (O2)와 (O3) (동시에 실행)
- Stage 3: (O4)와 (O5) (동시에 실행)
- Stage 4: (O6) (최종 출력 생성)
3. 병렬 처리의 이점
-
메모리 사용 효율: 병렬 연산은 파이프라인의 깊이를 줄여 메모리 사용량을 절감합니다. 각 스테이지가 필요한 메모리만을 사용하므로, 순차 파이프라인 방식(SPP)에 비해 전체 메모리 소비를 줄일 수 있습니다.
-
연산 시간 단축: (O2)와 (O3), (O4)와 (O5)를 동시에 실행하면 전체 연산 시간이 크게 단축됩니다. 예를 들어, 순차 파이프라인에서는 각 스테이지가 순서대로 수행되어야 하므로 각 연산이 차례로 처리되어야 하지만, 병렬 처리에서는 두 개의 연산이 동시에 완료됩니다. 이는 학습 처리량을 크게 높이는 데 기여합니다.
-
워밍업/쿨다운 시간 단축: 병렬 처리로 인해 파이프라인 스테이지의 깊이가 줄어들면서 초기 데이터가 모든 스테이지에 도달하는 데 걸리는 워밍업(warm-up) 시간과 마지막 데이터가 모든 스테이지를 통과하는 데 걸리는 쿨다운(cool-down) 시간이 단축됩니다. 이는 파이프라인에서 데이터 처리가 더 빠르게 순환되도록 하여 학습 속도를 높입니다.
요약
병렬 처리 가능한 연산을 파이프라인으로 나눔으로써, GPP는 연산 시간과 메모리 사용을 줄이며 학습 성능을 최적화할 수 있습니다. DAG 기반의 스테이지 분할은 DNN 모델 구조의 비선형적 특성을 그대로 반영하여 모델 학습을 더욱 효율적으로 만들 수 있는 중요한 방법입니다.
Q : 이게 기존 async pipeline parallelism 연구대비하여 어떤 점에서 강점이 있고 약점이 있을까?
Answer :
Graph Pipeline Parallelism (GPP)은 기존의 비동기 파이프라인 병렬 처리(asynchronous pipeline parallelism)와 비교하여 몇 가지 주요 강점과 약점을 가지고 있습니다. 이를 비교하여 GPP의 특성과 효율성을 구체적으로 설명하겠습니다.
GPP의 강점 (기존 Async Pipeline Parallelism 대비)
- 메모리 사용 최적화:
- GPP는 DNN의 비선형적인 그래프 구조를 반영하여 병렬적 연산을 최대한 활용합니다. 이는 파이프라인 스테이지의 깊이를 줄이고 메모리 사용량을 줄이기 때문에, DNN 학습에서 메모리 제약이 큰 대규모 모델에서는 효과적입니다.
- 기존 비동기 파이프라인 병렬 처리 방식에서는 모델 구조에 관계없이 모든 스테이지가 순차적 구성을 가지므로, 각 스테이지가 완료되지 않은 다른 스테이지의 출력을 기다려야 합니다. 이에 따라 메모리 사용량이 더 많아지며, 스테이지의 비효율적인 메모리 활용이 발생할 수 있습니다.
- 학습 처리량 증가:
- GPP는 비의존적 연산을 병렬로 실행할 수 있도록 DNN의 그래프 구조에 맞춘 스케줄링을 제공하여, 순차적 구성보다 더 높은 처리량을 제공합니다.
- 예를 들어, 병렬 연산을 동시에 수행할 수 있는 경우, 데이터가 각 스테이지에 빠르게 순환하며 학습 처리 속도를 높일 수 있습니다. 반면, 기존 비동기 방식에서는 스테이지 순차 실행으로 인해 일부 장치가 결과를 기다리며 유휴 상태에 놓이는 상황이 발생할 수 있습니다.
- 워밍업/쿨다운 단계 단축:
- GPP는 스테이지의 깊이를 줄이기 때문에 워밍업(warm-up)과 쿨다운(cool-down) 시간이 단축됩니다. 이는 학습 속도와 효율성을 증가시키며, 비동기 파이프라인 병렬 처리에서 발생하는 지연 시간을 줄입니다.
- 기존 비동기 방식은 순차적 스테이지 구성을 따르므로 깊은 파이프라인에서 각 단계가 순차적으로 채워지거나 배출될 때 상대적으로 많은 시간이 필요합니다. GPP는 이와 비교하여 처리량이 최적화된 병렬 스케줄링을 통해 이 단계를 효율적으로 관리합니다.
- 정합성 보장:
- GPP는 각 스테이지가 순차적이 아닌 그래프 형태로 연결되어 있지만, 연산 결과의 정합성(일관성)을 유지하도록 설계되었습니다. 이는 비동기 방식에서 발생할 수 있는 일관성 문제를 최소화할 수 있는 장점입니다.
- 기존 비동기 방식에서는 비동기적으로 진행되기 때문에 연산이 동시에 실행되면서 일부 장치가 최신 모델 파라미터를 사용하지 못하는 문제가 생길 수 있습니다. 이러한 일관성 문제는 GPP의 설계로 인해 크게 줄어듭니다.
GPP의 약점 (기존 Async Pipeline Parallelism 대비)
- 복잡성 증가:
- GPP는 DNN의 그래프 구조에 맞춘 스케줄링과 스테이지 분할을 수행해야 하기 때문에, 비동기 파이프라인 방식보다 설계 및 구현이 복잡합니다. DAG 기반 파이프라인 분할은 복잡한 알고리즘과 최적화 과정을 필요로 하며, 작은 모델에서는 오히려 이러한 복잡성으로 인해 성능 향상이 미미할 수 있습니다.
- 기존 비동기 방식은 상대적으로 단순하며 순차적으로 스테이지를 나누기 때문에 구현 및 유지보수가 용이합니다.
- 검색 공간의 증가:
- GPP는 병렬 연산을 고려한 다양한 스케줄링 옵션과 파이프라인 스테이지 분할을 탐색하기 때문에, 탐색 공간이 매우 커집니다. 이로 인해 최적의 GPP 전략을 찾기 위해 추가적인 연산이 필요하며, 검색 시간이 오래 걸릴 수 있습니다.
- 비동기 파이프라인 병렬 처리 방식은 순차적 스테이지 분할을 적용하여 탐색 공간이 제한적이므로, 최적의 전략을 찾는 속도가 빠릅니다.
- GPU 병렬성 활용 제한:
- GPP는 그래프 구조를 사용하여 병렬성을 최대한 활용하려 하지만, 모든 경우에 대해 비동기 파이프라인보다 높은 GPU 활용도를 보장하지는 않습니다. 특히 단순한 구조의 모델에서는 비동기 방식이 더 높은 성능을 보일 수 있습니다.
- 예를 들어, 순차적이거나 병렬 분기가 거의 없는 모델에서는 비동기 방식의 단순성이 GPP에 비해 오히려 성능상 유리할 수 있습니다.
- 대규모 모델에서의 스케일링 문제:
- GPP는 모델의 병렬적 구조에 의존하여 스케줄링을 최적화하지만, 대규모 모델이거나 병렬성이 적은 모델의 경우 기대한 만큼의 성능 향상을 보이지 않을 수 있습니다. 이러한 경우 GPP의 복잡성으로 인해 얻는 성능 개선이 제한적일 수 있습니다.
- 비동기 파이프라인 병렬 처리 방식은 모델 구조에 상관없이 모든 모델에 일정한 성능 향상을 제공할 수 있습니다.
요약
GPP는 기존 비동기 파이프라인 병렬 처리 방식에 비해 메모리 효율성, 학습 처리량, 정합성 보장 측면에서 우수한 성능을 발휘하지만, 구현의 복잡성 증가, 검색 공간의 확장, GPU 활용도 제한과 같은 단점이 있습니다. 모델의 구조와 연산 복잡도에 따라 두 방법의 성능 차이가 달라질 수 있으며, GPP는 특히 다중 분기와 병렬 처리가 많은 대규모 DNN 모델에서 큰 성능 향상을 기대할 수 있습니다. 반면, 간단한 모델에서는 기존 비동기 방식이 여전히 유효한 선택이 될 수 있습니다.
Q : 검색 공간의 증가로 인한 얼마만큼 오버헤드가 생기는지 논문에서 언급된 바가 있니? 그리고 어떠한 방법으로 이러한 오버헤드를 줄일수 있을지 생각해봐 주겠니?
Anaswer:
논문에서는 GPP(Graph Pipeline Parallelism) 방식의 복잡한 탐색 공간으로 인해 발생하는 검색 시간 오버헤드를 실제로 측정하고, 기존 방법과 비교하여 오버헤드의 정도를 설명하고 있습니다. GraphPipe 시스템의 최적화 과정에서 파이프라인 스테이지 분할과 마이크로배치 스케줄을 찾는 데 있어 최대 9-21배 더 빠른 검색 시간을 보여주며, 이는 기존 PipeDream과 Piper와 같은 순차적 파이프라인 방식에 비해 매우 효율적임을 강조합니다【5†source】.
탐색 공간 증가로 인한 오버헤드 원인
GPP는 모델의 병렬 가능성을 최대한 활용하기 위해 DAG 기반 스케줄링을 사용하고, 각 파이프라인 스테이지에 대해 다양한 병렬화 전략을 고려해야 합니다. 따라서,
- 병렬적 스테이지 분할,
- 마이크로배치 크기 최적화,
- 디바이스 할당 등
모든 변수 조합을 탐색해야 하므로 검색 공간이 매우 커지게 됩니다. 특히, 비선형적 모델 구조에서는 파이프라인 스테이지가 더욱 다양하게 분할될 수 있기 때문에 최적의 전략을 찾는 데 드는 연산 비용이 상당히 증가합니다.
오버헤드를 줄이는 방법 제안
- 휴리스틱 기반 검색 최적화:
- 모델의 특성에 맞는 휴리스틱(Heuristic)을 도입하여 탐색 공간을 줄이는 방법을 고려할 수 있습니다. 예를 들어, 병렬 처리가 가능한 경우와 그렇지 않은 경우를 사전에 구분하거나, 특정 병렬화 조건(예: 깊이별 분기 수)에 대한 우선순위를 부여하여 검색 속도를 높이는 방식입니다.
- 예시로, 모든 가능한 분할을 탐색하는 대신 병렬 분기가 많은 구조에서는 병렬성을 최대한 활용하는 방향으로 탐색을 제한할 수 있습니다.
- 그래프 분할 최적화:
- GPP에서 그래프를 여러 하위 그래프로 나누어 병렬로 최적화를 수행하면 탐색 시간을 줄일 수 있습니다. 예를 들어, DAG를 계층 구조로 분할하고, 독립적인 하위 그래프에서 동시에 최적화 작업을 진행한 후 통합하는 방식입니다. 이 방법은 전체 그래프를 대상으로 최적화를 수행하는 것보다 시간을 단축할 수 있습니다.
- 샘플링 기반 탐색:
- 전체 검색 공간을 탐색하는 대신, 일부 유망한 경로를 샘플링하여 평가한 후 성능이 우수한 경로에 집중하는 방법입니다. 예를 들어, 탐색 초기에는 다양한 분할 전략을 무작위로 샘플링하고, 최적화가 진행될수록 성능이 좋은 전략에 더 많은 연산 자원을 할당하는 방식입니다. 이는 탐색 공간을 줄이면서도 최적화 성능을 크게 손상시키지 않을 수 있습니다.
- 사전 학습된 모델 기반 탐색:
- 유사한 구조의 모델에 대해 최적의 병렬화 전략을 이미 학습한 모델을 사용하여 검색 시간을 줄이는 방법입니다. 예를 들어, 과거에 최적화된 모델을 기반으로 현재 모델의 병렬화 전략을 예측하고, 이를 초깃값으로 사용하여 탐색 공간을 빠르게 좁힐 수 있습니다.
- 계층적 탐색 알고리즘:
- GPP의 탐색 과정에서 계층적 탐색 구조를 사용하여 복잡한 모델을 먼저 큰 단위로 나누고, 이후 각 단위에서 세부적인 최적화를 수행하는 방식입니다. 예를 들어, 상위 레벨에서는 전체 모델의 주요 스테이지 구조를 결정하고, 하위 레벨에서 각 스테이지의 구체적인 스케줄링과 마이크로배치 최적화를 수행하는 구조입니다. 이를 통해 검색 공간의 복잡도를 단계적으로 줄일 수 있습니다.
요약
이와 같은 다양한 검색 공간 축소 기법을 적용하면 GPP의 검색 시간 오버헤드를 줄이고, 보다 빠르게 최적의 병렬화 전략을 찾을 수 있습니다.
Q : 논문에 제시된 알고리즘에 대해서 아주 자세하게 예를 들어서 설명해줘
Answer :
논문에서 제시된 GraphPipe 시스템의 알고리즘은 DNN(딥러닝 네트워크)의 구조를 기반으로 그래프 기반 파이프라인 병렬 처리를 최적화하는 데 사용됩니다. 이 알고리즘은 세 가지 주요 구성 요소로 나뉩니다: 파이프라인 스테이지 분할기, 마이크로배치 스케줄러, 그리고 분산 런타임입니다. 이 과정은 최적의 파이프라인 전략을 찾고 병렬 처리를 극대화하는 데 목표를 둡니다.
여기서 각 단계별로 예시를 들어 설명하겠습니다.
1. 파이프라인 스테이지 분할기 (Pipeline Stage Partitioner)
먼저 DNN의 그래프를 여러 개의 파이프라인 스테이지로 나눕니다. 각 스테이지는 연산을 나타내는 노드들의 묶음이며, 그래프의 DAG(Directed Acyclic Graph) 구조를 기반으로 분할됩니다.
예시 그래프
O1
/ \
O2 O3
| |
O4 O5
\ /
O6
이 예시에서:
- 각 노드 (O1, O2, \ldots, O6)는 DNN의 연산을 나타냅니다.
- 각 간선은 데이터 의존성을 나타내며, 이전 노드의 연산 결과가 다음 노드의 입력으로 사용됨을 의미합니다.
분할 과정
- 그래프 분할 및 병렬 처리 가능성 탐색: 알고리즘은 그래프 내에서 병렬로 실행할 수 있는 연산을 식별합니다. 예를 들어, 노드 (O2)와 (O3)는 서로 독립적이기 때문에 동시에 실행될 수 있습니다.
- 파이프라인 스테이지 생성:
- Stage 1: (O1) (초기 입력 처리)
- Stage 2: (O2)와 (O3) (동시에 실행 가능)
- Stage 3: (O4)와 (O5) (동시에 실행 가능)
- Stage 4: (O6) (최종 출력 생성)
이 분할을 통해 각 스테이지는 가능한 한 병렬로 실행되며, 모델의 병렬성을 최대한 활용할 수 있습니다.
2. 마이크로배치 스케줄러 (Static Micro-Batch Scheduler)
각 스테이지에 대해 마이크로배치 크기를 결정하고, 각 스테이지의 순서를 최적화하여 GPU 메모리 사용량을 최소화하고, 각 스테이지가 병렬로 최대한 효율적으로 작동할 수 있도록 합니다.
마이크로배치 스케줄링 예시
각 파이프라인 스테이지는 마이크로배치를 실행하며, 동시에 실행될 수 있는 연산을 고려하여 마이크로배치 크기를 최적화합니다. 위의 예시에서:
- Stage 2와 Stage 3은 병렬적으로 실행될 수 있으므로, 각각에 대해 마이크로배치를 2개의 크기로 설정하여 메모리 사용을 최적화할 수 있습니다.
- Stage 4는 마지막 스테이지이므로, 필요에 따라 큰 마이크로배치를 사용하여 연산 속도를 증가시킬 수 있습니다.
스케줄링의 최적화
- Forward와 Backward Pass 스케줄링: 각 마이크로배치는 GPU 메모리 사용을 최소화하기 위해, Forward Pass(순방향 연산)가 완료되자마자 Backward Pass(역방향 연산)가 실행되도록 스케줄링됩니다. 예를 들어, Stage 2의 (O2)와 (O3)가 동시에 Forward Pass를 수행한 후, 두 연산에 대한 Backward Pass가 바로 실행됩니다.
- 메모리 제한 조건 확인: 각 마이크로배치의 크기와 스케줄링은 GPU 메모리 제한에 맞춰 조정됩니다. 예시에서는 Stage 2와 Stage 3에 독립적으로 2개의 마이크로배치를 할당함으로써 메모리 사용을 최적화합니다.
3. 분산 런타임 (Distributed Runtime)
최종적으로, GraphPipe의 분산 런타임이 이전 단계에서 최적화된 파이프라인 전략을 실제로 실행하며, 각 GPU에 작업을 분배하고 효율적인 데이터 통신을 보장합니다.
예시 실행
- 단계 1: 입력 데이터가 (O1)에서 처리됩니다.
- 단계 2: (O2)와 (O3)에서 병렬로 연산이 수행됩니다.
- 단계 3: (O4)와 (O5)에서 병렬 연산이 진행되며, (O2)와 (O3)의 결과를 입력으로 사용합니다.
- 단계 4: 마지막으로 (O6)에서 최종 연산이 이루어집니다.
분산 런타임은 각 파이프라인 스테이지의 연산을 병렬로 배치하여 최대한의 GPU 활용도를 달성합니다.
요약 및 알고리즘의 장점
GraphPipe 알고리즘은 다음과 같은 방식으로 성능을 극대화합니다:
- 병렬 처리 최적화: 그래프 구조를 반영하여 독립적인 연산을 병렬로 실행함으로써 전체 처리 속도를 높입니다.
- 메모리 사용 최적화: 각 스테이지에 맞는 최적의 마이크로배치 크기를 선택하여 GPU 메모리 제한을 준수하면서도 연산을 효율적으로 수행할 수 있습니다.
- 분산 런타임의 효율적 실행: 최적화된 스케줄을 통해 각 GPU의 활용도를 극대화하며, 연산 간 통신 지연을 최소화합니다.
이 알고리즘을 통해 기존 순차적 파이프라인 방식보다 더 높은 처리량과 메모리 효율을 얻을 수 있습니다.