Conversation
This comment has been minimized.
This comment has been minimized.
avtc
marked this pull request as draft
September 14, 2026 19:28
avtc
force-pushed
the
feature/improvements-to-multi-gpu-quantization
branch
from
September 14, 2026 21:32
5b49ec9 to
0f0ea17
Compare
avtc
marked this pull request as ready for review
September 14, 2026 21:33
Collaborator
|
/azp run Unit-Test-CUDA-AutoRound |
|
Azure Pipelines successfully started running 1 pipeline(s). |
…rches, memory-aware pool placement, auto experts-impl pick Device-local batched searches (iters=0 OptRTN and iters>0 SignRound): same-shape search calls stack per (device, shape, dtype, bits, group, resolved callable) and run on the GPUs the weights already live on -- idle devices take the overflow. Rows bit-identical by construction; mid-batch OOM keeps applied results; the serial lane's OOM->CPU fallback is honored at every site; singletons fall back to serial. Calibration-data pool placement (--calibration_data_device auto|off|cpu|csv): per-block water-fill placement across GPUs under a first-principles need model (computed working allowance, measured collection-window term, deduped 14 B/param tuning state, per-device activation charge with expert-home attribution). Unblocks MoE blocks whose primary cannot host the pools beside the activation window. Pure memory behavior; chunk values bit-identical. Atomic MoE expert placement + per-device grouped-experts plans: the data-driven allocator places whole experts (atomic groups) instead of scattering projection Linears; the grouped-GEMM fast path runs one stacked GEMM per (slot, device) group so it stays eligible under mapped multi-GPU placement. Alignment-only accelerate hooks are exempted from its hook check; calibration hooks still fall back by design. One-shot auto pick of the experts implementation: when grouped tuning cannot fit (per-device qdq stack retention + guaranteed in-loop state vs the live free probe), the run switches to linear_loop BEFORE the first MoE loop, with per-device term logging. Explicit AR_MOE_EXPERTS_IMPL values are never overridden. Upstream fixes surfaced by the new instrumentation: layer_config rebuilt the whole compression-plan dict per read (~27 s per MoE block of invisible dict-copying in the pack loops; now cached/hoisted, pack 29 -> 1.2 s); immediate pack ran after mv_module_from_gpu (CPU packing; reordered, mv 4.5 -> 1.2 s, bit-identical); compiled blocks pinned FX/dynamo example tensors (~2-4 GiB monotonic growth; reset at block end); estimator act_bits read off orig_layer for V2 wrappers. Instrumentation (opt-in): [perf] block-phase summary, OOM tensor census with holder attribution, AR_PERF_COUNTERS, routed-shape recorders. Measured on a 300B-A21B MoE (8x3090): iters=0 quant searches 61.4 -> 9.40 s, MoE block 123 -> ~26 s, full run ~34 min; iters=20 wrap search 80 -> 7.7 s, tune loop 62.8 -> 38.1 s (lean) / 99.3 -> 47.7 s (spread), full 80-block run 2 h 29 m; tuning losses identical to serial. 4x3090 capacity unlock via the auto pick (166 s/block, linear_loop). 3,100+ test lines across 10 files. Signed-off-by: avtc <tarasenkov@gmail.com>
avtc
force-pushed
the
feature/improvements-to-multi-gpu-quantization
branch
from
September 15, 2026 09:19
0f0ea17 to
a44eb52
Compare
Collaborator
|
/azp run Unit-Test-CUDA-AutoRound |
|
Azure Pipelines successfully started running 1 pipeline(s). |
avtc
added a commit
to avtc/auto-round
that referenced
this pull request
Sep 18, 2026
…eserved on the tune device Rework of the huge-layer snapshot parking along two axes. ONE HOME, STRUCTURAL (replaces the separate utils/snapshot_parking.py module): compressors/utils.py now carries collect_best_params_local and snapshot_best_params byte-identical to the multi-GPU improvements PR (intel#2357) plus this lane's ladder in the same file, so the two snapshot implementations meet in one place at merge time -- git, not a kit note, forces the analysis. SAME-GPU SLOT WITH WINDOW ACCOUNTING (the 24 GB expectation): the snapshot is now a BestParamsSlot reserved BEFORE the tune loop. The device ladder prefers the layer's own device whenever the snapshot fits beside the row-window floor (free - snapshot >= 1024 rows x in_features x fp32 x ~6 live arrays, the row-block machinery's own anchors), then an idle CUDA peer (10% headroom), then the host. Reserving upfront means row_block_bounds' per-forward free-memory probe sees the reduced pool from iteration 0: windows shrink in favor of keeping the snapshot, which removes both the multi-second host copy per improving iteration and the transient OOM of windows sized on the pre-snapshot pool. Refreshing an on-device slot copies into existing buffers; reservation failure degrades to the historical host path. quantize_layer_outside_block reserves the slot for layers above the chunking budget; small layers keep the exact cache_device path. _best_param_device is removed (the slot subsumes it); its contract tests move to the ladder tests. Signed-off-by: avtc <avtc@users.noreply.github.com>
avtc
added a commit
to avtc/auto-round
that referenced
this pull request
Sep 19, 2026
…-> host) Adopting the streaming branch's fallback philosophy, one step further: the clone attempt itself is the test. The snapshot first duplicates beside the weights; on failure it falls through to the freest visible accelerator of the same type (most free first, every candidate still guarded by a real attempt-and-catch at clone time); when no accelerator can hold it, it parks on the host with a WARNING. The successful route is sticky per block (retried first on later improving iterations) and the host is terminal - no mid-tune flip-flopping back onto accelerators. The activation-floor routing is gone from the block path: placement no longer consults any prediction, so the estimator's tune-loop role ends (placement keeps it). act_floor_bytes stays in the signature for call-site compatibility and no longer routes anything. This also answers the observed gap: the floor-based ladder routed the predictor tree to an idle peer by prediction (its WARNING paths never fired in any real run), while the clone-time catches inherited from intel#2357 only covered the local-copy failure. Now every placement decision is made by attempting it. Signed-off-by: avtc <avtc@users.noreply.github.com>
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.
Description
Multi-GPU tuning for large MoE models (validated end-to-end on a 300B-A21B MoE, 8x3090, W4A16): device-local batched quantization searches, calibration-data pool placement, atomic expert placement with per-device grouped-experts plans, and a memory-model-driven auto pick of the experts implementation. Plus four upstream bugs the new instrumentation surfaced (fixes benefit single-GPU users too).
Features
--calibration_data_device auto | off | cpu | cuda:1,cuda:2 | 1,2(CLI and Python API). Per-block placement of the calibration input/output pools: they stay on the primary GPU when they fit beside the activation window, and are spread across the other GPUs otherwise, placed so that every GPU's peak VRAM during tuning stays close to the same level. Placement decisions come from a memory model of the block (activation window, collection retention, tuning state, and activation estimates computed per GPU from the modules whose weights live there).nn.ModuleListcontainers, and the MoE unfuse path builds a plain container.AR_MOE_EXPERTS_IMPL=auto(new value of the existing env var, now the default). Predicts the per-device VRAM of grouped tuning before the first MoE block and selectslinear_loopfor the run when grouped exceeds the free memory; explicit values take precedence.Upstream fixes (single-GPU users benefit too)
layer_configrebuilt the full compression-plan dict on every read (~50 ms on a 300B plan); the pack loops read it once per module, which cost ~27 s per MoE block. The reads are hoisted.--enable_torch_compile, dynamo/FX caches retain tracing artifacts across blocks (~5 GiB in the block-3 OOM census on the 300B lane) until the recompile limit forces an eager fallback. Blocks wrap fresh modules, so no compiled graph is reused across blocks; the block-boundary dynamo reset (when compilation is enabled) frees the dead caches and keeps retention from accumulating.act_bitswas read off the wrapper instead of the wrapped layer); it now reads quantization attributes throughorig_layer.Instrumentation (opt-in)
AR_PERF_COUNTERSemits a per-block phase summary; an OOM tensor census with holder attribution is installed by the CLI; pool-placement decisions are logged. The three upstream fixes were found with these tools.Measured results (300B-A21B MoE, 80 blocks; iters=0 lane = optimized RTN, symmetric scheme; iters=20 lane = SignRound V2)
Per-block phase walls on 8x3090, serial baseline (with fixes unlocking iters=20) vs this branch:
Full runs, same rig and model:
VRAM stays flat across blocks on the branch's full runs. On 5 and more GPUs the grouped-experts path stays active.
Numerical parity: iters=0 outputs are bit-identical to the serial path; at iters=20 the tuning losses match the serial path within run noise (7.305e-11 to 2.670e-11 batched, 2.671e-11 serial).
New knobs
--calibration_data_device auto | off | cpu | cuda:1,cuda:2 | 1,2(CLI and Python API): calibration pool placementAR_MOE_EXPERTS_IMPL=auto: new value of the existing env var, picks grouped vs linear_loop by predicted memory fitAR_DISABLE_BATCHED_SEARCH=1: serial search fallbackAR_DISABLE_MULTIGPU_SEARCH=1: keeps search batches on the devices hosting the weightsAR_SEARCH_BATCH_GB: VRAM cap for stacked search batchesAR_PERF_COUNTERS=1: per-block phase timingAll documented in
docs/environments.mdand its CN counterpart.Tests
About 3,100 lines of new CPU-runnable tests: search batching and dispatch, pool placement, grouped-experts plans and atomic placement (including a CUDA-gated two-device test), the auto linear_loop pick, pool release and writer ordering.
Type of Change
New feature (performance) + bug fix
Related Issues
Relates to #2303 (keeps the grouped-experts fast path active when experts span several GPUs)
Checklist Before Submitting
/azp run Unit-Test-CUDA-AutoRound.