|
| 1 | +# MegatronMIMO Intra-Microbatch Reordering |
| 2 | + |
| 3 | +Intra-microbatch reordering rebalances the per-sample vision load of each |
| 4 | +micro-batch across a module's data-parallel ranks in non-colocated |
| 5 | +MegatronMIMO training. It removes the straggler that appears when one |
| 6 | +data-parallel rank happens to draw the heaviest images every step. |
| 7 | + |
| 8 | +This page is the stable overview of what the feature does, how to enable it, |
| 9 | +and which constraints are durable. The implementation lives in |
| 10 | +`megatron.bridge.data.megatron_mimo.reorder_buffer`; the Qwen3.5-VL example |
| 11 | +under `examples/megatron_mimo/qwen35_vl/` wires it end to end. |
| 12 | + |
| 13 | +## What It Is |
| 14 | + |
| 15 | +In a non-colocated MegatronMIMO run the vision encoder and the language model |
| 16 | +run on disjoint rank groups, each with its own data-parallel size. With |
| 17 | +scalable data parallelism (`megatron_mimo_scalable_dp`), every rank reads only |
| 18 | +its own shard of each global micro-batch, so the images a rank must encode are |
| 19 | +whatever the sampler happened to assign to it. Image sizes vary widely, so the |
| 20 | +per-rank vision work varies too, and the slowest rank gates every step. |
| 21 | + |
| 22 | +The reorder buffer wraps the training data iterator and, for each micro-batch |
| 23 | +(or window of micro-batches), does three things: |
| 24 | + |
| 25 | +1. Computes a per-sample cost on every rank from fields that are identical on |
| 26 | + the vision and language modules: the image-placeholder token count in |
| 27 | + `input_ids` (proportional to the number of vision patches) and, optionally, |
| 28 | + the real token count from `attention_mask`. |
| 29 | +2. All-gathers the costs over the module's data-parallel group and computes one |
| 30 | + balanced assignment of samples to ranks. The assignment is a deterministic |
| 31 | + function of the costs, so the vision and language modules compute the same |
| 32 | + one without talking to each other. |
| 33 | +3. Exchanges samples with a single ragged `all_to_all` so each rank ends up |
| 34 | + holding its assigned samples in a canonical order. |
| 35 | + |
| 36 | +Because both modules apply the same assignment, sample *i* on vision replica |
| 37 | +*r* is still sample *i* on language replica *r*, and the `BridgeCommunicator` |
| 38 | +fan-out stays aligned. Balancing is done over the canonical grid (the least |
| 39 | +common multiple of the module data-parallel sizes), so modules with different |
| 40 | +data-parallel sizes, including a module with data-parallel size 1, agree on |
| 41 | +the same order. A data-parallel-1 module has nothing to exchange and simply |
| 42 | +permutes its whole micro-batch locally; that permutation runs synchronously on |
| 43 | +the training thread (about 14 ms per micro-batch of 4 samples on A100) because |
| 44 | +there is no exchange to overlap. |
| 45 | + |
| 46 | +By default the exchange for the next window runs on a background thread with a |
| 47 | +dedicated NCCL process group, overlapping with the current window's compute. |
| 48 | + |
| 49 | +## When to Use It |
| 50 | + |
| 51 | +Reordering is a good fit when all of the following are true: |
| 52 | + |
| 53 | +- the run is non-colocated MegatronMIMO with `megatron_mimo_scalable_dp=True` |
| 54 | +- at least one module has data-parallel size 2 or more |
| 55 | +- image load varies across samples (document, receipt, or mixed text-and-image |
| 56 | + SFT data), so per-rank vision time is the per-step straggler |
| 57 | + |
| 58 | +It does not help text-only training, colocated single-module runs, or data |
| 59 | +where every sample carries the same number of similarly sized images. |
| 60 | + |
| 61 | +## Bridge Configuration |
| 62 | + |
| 63 | +All fields live on `DirectHFSFTDatasetConfig` and default to off. |
| 64 | + |
| 65 | +| Field | Default | Meaning | |
| 66 | +|---|---|---| |
| 67 | +| `megatron_mimo_scalable_dp` | `False` | Read only this rank's canonical-grid shard. Required by reordering. | |
| 68 | +| `megatron_mimo_intra_microbatch_reorder` | `False` | Enable the reorder buffer. | |
| 69 | +| `megatron_mimo_reorder_encoder_cost_weight` | `1.0` | Cost weight per vision patch. | |
| 70 | +| `megatron_mimo_reorder_language_cost_weight` | `0.0` | Cost weight per real language token; `0.0` balances on vision load only. | |
| 71 | +| `megatron_mimo_reorder_overlap` | `True` | Exchange the next window on a background thread. | |
| 72 | +| `megatron_mimo_reorder_window_size` | `1` | Micro-batches balanced together in one exchange. | |
| 73 | + |
| 74 | +Only the ratio of the two cost weights matters; at least one must be positive. |
| 75 | + |
| 76 | +The Qwen3.5-VL example exposes the same fields as `--scalable-dp`, |
| 77 | +`--intra-microbatch-reorder`, `--reorder-encoder-cost-weight`, |
| 78 | +`--reorder-language-cost-weight`, `--no-overlap-intra-microbatch-reorder`, and |
| 79 | +`--reorder-window-size`: |
| 80 | + |
| 81 | +```bash |
| 82 | +python examples/megatron_mimo/qwen35_vl/finetune_qwen35_vl.py \ |
| 83 | + --component "language=tp=1,pp=1,dp=2,rank_offset=0" \ |
| 84 | + --component "images=tp=1,dp=2,rank_offset=2" \ |
| 85 | + --scalable-dp --intra-microbatch-reorder \ |
| 86 | + ... |
| 87 | +``` |
| 88 | + |
| 89 | +Overlap is refused under `CUDA_DEVICE_MAX_CONNECTIONS=1`: with a single |
| 90 | +hardware queue the prefetch thread's all-to-all and the DDP all-reduce execute |
| 91 | +in issue order, that order differs across ranks, and training deadlocks |
| 92 | +(reproduced on a 4-rank run and on a 6-rank TP=2 run). Use |
| 93 | +`--no-overlap-intra-microbatch-reorder` in that case; it issues both |
| 94 | +collectives from the training thread and completed 1500 iterations under the |
| 95 | +same setting. Megatron Bridge does not require the variable for tensor |
| 96 | +parallelism; it is a Megatron-LM sequence-parallel performance setting, so TP |
| 97 | +users choose between that setting with the non-overlapped reorder, or overlap |
| 98 | +with the variable unset. |
| 99 | + |
| 100 | +## Stable Constraints |
| 101 | + |
| 102 | +| Configuration | Status | |
| 103 | +|---|---| |
| 104 | +| Heterogeneous module data parallelism (for example vision dp 1 or 2 with language dp 2 or 4) | Supported. Balancing uses the canonical grid; a dp-1 module reorders locally. The encoder data-parallel size must not exceed the language data-parallel size: Megatron Core's bridge fan-in with variable per-sample image-token counts is not implemented and asserts on the first forward step. | |
| 105 | +| Language pipeline parallelism > 1 | Supported. Every language stage receives `input_ids` so all stages compute the same assignment. | |
| 106 | +| Encoder pipeline parallelism > 1 | Not supported; the example raises before training starts. | |
| 107 | +| `--pad-to-seq-length false` (variable batch width) | Not supported with reordering; the example raises before training starts. Exchanged samples are concatenated back into one micro-batch, so all ranks must pad to the same length. | |
| 108 | +| `micro_batch_size` not divisible by the canonical grid size | Rejected by the canonical loader. | |
| 109 | +| `drop_last=False`, or a dataloader type other than `single` / `cyclic` | Rejected by scalable data parallelism. | |
| 110 | +| Expert tensor parallelism > 1 | Rejected by scalable data parallelism. | |
| 111 | +| Tensor parallelism > 1 | Validated (language tp 2 with and without vision tp 2). | |
| 112 | +| Context parallelism > 1 | Untested. | |
| 113 | + |
| 114 | +A full MIMO run with an exchanging module needs at least three GPUs, which |
| 115 | +exceeds the two-GPU functional-test budget. CI covers the balancing and |
| 116 | +serialization logic with CPU-emulated unit tests, and the real Gloo/NCCL |
| 117 | +exchange, including the overlapped prefetch thread, with a two-rank functional |
| 118 | +test; full MIMO runs are validated manually. |
| 119 | + |
| 120 | +## Expected Metric Changes |
| 121 | + |
| 122 | +| Metric | Expected Change | Conditions | Evidence | |
| 123 | +|---|---|---|---| |
| 124 | +| per-rank vision load spread | down | module data-parallel size 2 or more, varied image sizes | measured | |
| 125 | +| `step_time` | flat to slightly down | every module has data-parallel size 2 or more, overlap on | measured | |
| 126 | +| `step_time` | slightly up | a module has data-parallel size 1 (its local permutation is synchronous) | measured | |
| 127 | +| `step_time` | up | overlap off (`--no-overlap-intra-microbatch-reorder`) | measured | |
| 128 | +| `peak_memory` | up by up to two extra windows of micro-batches per data rank | overlap on; grows with `megatron_mimo_reorder_window_size` | expected | |
| 129 | + |
| 130 | +Balancing cannot remove the imbalance entirely: every rank keeps the same |
| 131 | +number of samples, so with few samples per rank and a bimodal image-size |
| 132 | +distribution the reachable spread is bounded by the largest single image. |
| 133 | + |
| 134 | +## Representative Validation Patterns |
| 135 | + |
| 136 | +On one 8×A100 node with Qwen3.5-0.8B on cord-v2 (sequence length 2048, |
| 137 | +bf16), language dp 4 with vision dp 4 at micro-batch 8 cut the mean |
| 138 | +max-minus-min image-token spread across vision ranks from `643` to `421` and |
| 139 | +lowered iteration time by about 2% with overlap on. A 3-rank run with vision |
| 140 | +dp 1 was about 5% slower with overlap and 10% slower without, because the dp-1 |
| 141 | +module's permutation is synchronous. In the dp 4 run the per-micro-batch sum |
| 142 | +of image tokens over all vision ranks matched the unreordered run for all 40 |
| 143 | +micro-batches. On language dp 2 + vision dp 2 the reorder off/on pair had |
| 144 | +identical iteration-1 and iteration-2 losses, checkpoint resume reproduced the |
| 145 | +continuous run, and an overlapped run completed 3000 iterations. Under |
| 146 | +`CUDA_DEVICE_MAX_CONNECTIONS=1` without overlap, language tp 2 dp 2 + vision |
| 147 | +dp 2 completed 10000 iterations; language tp 2, pp 2, and tp 2 with vision tp 2 |
| 148 | +each completed 1000 iterations. Treat these as patterns to reproduce on the |
| 149 | +target model and data, not as fixed gains. |
| 150 | + |
| 151 | +## Feature Interactions |
| 152 | + |
| 153 | +- **In-batch sequence packing** (`enable_in_batch_packing`): reordering runs in |
| 154 | + the data iterator, before the forward step packs each language shard, so the |
| 155 | + two compose. Packing drops padding, so the exchange transfers padded rows but |
| 156 | + model compute is unaffected. |
| 157 | +- **Checkpoint resume**: reordering changes which rank holds a sample, not how |
| 158 | + many samples are consumed, so the resume arithmetic of the canonical sampler |
| 159 | + is unchanged. |
| 160 | +- **Cost weights and the language term**: setting |
| 161 | + `megatron_mimo_reorder_language_cost_weight > 0` counts real tokens from |
| 162 | + `attention_mask`; the example ships `attention_mask` on every stage for this |
| 163 | + purpose and the forward step drops it before the model. |
| 164 | + |
| 165 | +## Related Docs |
| 166 | + |
| 167 | +- [Packed Sequences](packed-sequences.md) |
| 168 | +- Example: `examples/megatron_mimo/qwen35_vl/finetune_qwen35_vl.py` |
0 commit comments