【训练营】Pipeline 并行自定义布局 - #209
Open
Dayuxiaoshui wants to merge 2 commits into
Open
Dayuxiaoshui wants to merge 2 commits into
Dayuxiaoshui wants to merge 2 commits into
Conversation
Balancing only the Transformer layers misses the two modules that are pinned to the ends of the pipeline: the embedding always sits on stage 0 and the final norm plus lm head on the last stage. On a large-vocabulary model the lm head, not the layers, is the slowest part of the last stage. --pipeline_layer_costs now accepts optional "E:<cost>" and "L:<cost>" entries alongside the per-layer costs. They take no layer slot; they only add a constant to the first and last segment in the balancing DP. The trailing constant applies only to the state that closes the last stage, so the optimal substructure still holds. suggest_pipeline_layout.py grows the matching --embedding-cost / --lm-head-cost so an offline suggestion and the runtime solver agree. Also add the regression that was missing for the parallelism claims: a layout x PP/DDP/TP matrix that checks every combination against one single-GPU reference, and a synthetic LLMC asset generator so the matrix can run where the llm.c starter pack cannot be downloaded. Measured on 2 x H20, 8 layers / 384 hidden / vocab 50304 / seq 512: uniform 4,4 runs at 86,628 tok/s, while "1x8,L:4.5" picks 6,2 and runs at 102,904 tok/s (+18.8%). The raw parameter-count ratio (L:10.9) overshoots to 7,1 and only gains 6.8%, so the cost still has to be measured rather than derived from parameter counts. Verified: 11/11 layout unit tests, and 14/14 matrix cases on 8 x H20 matching the single-GPU reference loss within 1e-6, with 101/101 per-parameter gradients matching at atol=1e-5 on the 11 non-TP cases.
JYMiracle305
self-requested a review
September 20, 2026 01:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR: Configurable Pipeline Layouts
Commit covered
19 files changed, 1525 insertions(+), 93 deletions(-).
Summary
GPT-2 and LLaMA 3 can now assign a custom, non-uniform number of Transformer layers to each pipeline-parallel stage, instead of only the built-in uniform split. A new
nn::parallel::PipelineLayoutis the single source of truth for "which Transformer layers (and the embedding / final-norm / lm-head) live on which physical PP stage," and it's consumed identically by model construction,PipelineParallelstage setup, and both LLMC checkpoint loaders — so layer assignment can't drift between subsystems.Layout can be specified four ways
--pipeline_layer_partition=4,8,6,6: one entry per PP stage, entries must be positive integers and sum to the model's real layer count. Requires--virtual_pipeline_parallel=1.--pipeline_layer_costs=10,1,1,1,1,1: one relative cost per layer (e.g. from a profiler); a DP over contiguous partitions (O(stages * layers^2)) picks the split that minimizes the slowest stage's total cost, keeping layers contiguous and in order. Mutually exclusive with manual partition.--pipeline_chunk_layout=0:3,1:3,1:3,0:3or--pipeline_model_parallel_layout='Et*3||t*3|t*6NL': explicit ordered chunk-to-stage ownership, removing the previous fixedglobal_chunk = local_chunk * pp_size + stageround-robin restriction forvirtual_pipeline_parallel > 1.Other pieces
PipelineLayout::layer_ranges/stage_for_layer/owns_embedding/owns_final_norm/owns_lm_head— query API used by model construction and checkpoint loaders; storedthread_localsince one process can host multiple training threads, each representing an independent global rank.PipelineParallel::GetStageInfo— compatibility projection for existing scheduler code.scripts/suggest_pipeline_layout.py— offline tool that turnsPROFILE_MODErecords (or user-supplied costs) into a ready-to-paste--pipeline_layer_partitionvalue, dropping each layer's first profiler sample by default to avoid CUDA-warmup skew.checkpoint_loader.{h,cc}andmain.ccupdated to resolve and validate the layout (after reading the real layer count from the LLMC checkpoint header / config) before model construction, and to print the normalized final layout on the main rank at startup.--pipeline_parallel, wrong layer-count sum, non-positive/empty entries, custom physical partition combined with--virtual_pipeline_parallel != 1, and manual partition + auto-balance cost both set. Full error-message list indocs/pipeline_layout_guide.md.--dump_gradients=DIRon the GPT-2 example exports all non-empty parameter gradients after the first optimizer step, remapping each PP rank's local layer number to a global one so single-GPU and custom-PP gradient dumps can be diffed directly viascripts/precision_check/precision_compare.py.Docs added
docs/pipeline_layout_guide.md— user-facing flag reference and syntax.docs/pipeline_layout_report.md— design/implementation notes, the DP algorithm, and test results.docs/pipeline_layout_test_log.md— raw logs backing the results below.Tests
tests/distributed/test_pipeline_layout.cc(CPU, ctest-registered) — manual partition (4,8,6,6), full layer-to-stage reverse lookup, special-module ownership, default vPP rotation, and the error cases above.tests/distributed/test_pipeline_layout_suggestion.py— unit tests for the cost-based auto-balance DP and profiler-record parsing.tests/distributed/test_pipeline_layout_e2e.sh— 2-GPU CUDA/NCCL script (needs GPT-2 124M LLMC checkpoint; not registered in defaultctestsince it needs 2 GPUs + external model assets): runs a single-GPU baseline vs. a custom two-stage layout, then diffs the final layout string, fp32 loss, gradient-file set, and per-parameter gradients.Reported results (see
docs/pipeline_layout_report.mdfor full detail): 10/10 CPU layout/suggestion tests pass; CPU build of GPT-2/LLaMA3/Mixtral compiles and links cleanly. On 2×H200, GPT-2 124M with a custom4,8two-stage layout matches single-GPU loss to within2e-6(well inside the fp321e-5tolerance used), and all 149/149 per-parameter gradients match atatol=1e-5, rtol=0with no missing files. A profiler-suggested7,5layout (vs. default6,6) measured 9.45% higher throughput and 130MB lower peak stage memory on the same 2×H200 setup.Risk / compatibility
--virtual_pipeline_parallel != 1rather than silently producing wrong execution order — the fixed vPP round-robin can't unambiguously absorb a physical layer-count list.--dump_gradientscopies gradients to CPU synchronously and is intended for correctness verification only — should not be enabled during performance benchmarking.Test plan
For the CUDA/NCCL 2-GPU pipeline-layout regression: