Skip to content

feat: data-parallel block tuning via --parallel_quantization - #2351

Open
avtc wants to merge 1 commit into
intel:mainfrom
avtc:feature/ddp-parallel-tuning
Open

feat: data-parallel block tuning via --parallel_quantization#2351
avtc wants to merge 1 commit into
intel:mainfrom
avtc:feature/ddp-parallel-tuning

Conversation

@avtc

@avtc avtc commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a single-process data-parallel tuning engine behind one CLI flag: --parallel_quantization {off, auto, N}. off (default) keeps the serial single-GPU loop unchanged; auto/N>=2 pin the replica world to the largest power-of-two <= visible CUDA devices, subject to a free-VRAM mirror guard. On multi-GPU boxes the idle GPUs now do the tuning work.

How it works (auto_round/algorithms/quantization/sign_round/data_parallel.py):

  • Each tuning block is mirrored onto the plan devices; replicas tune on disjoint calibration shards, so the effective batch matches the serial run's data coverage.
  • Gradients are exchanged via bf16 transport plus a sign-cast exchange for sign-SGD steps (bitwise-identical across replicas); the reduce is an in-process halving-doubling allreduce — no torchrun, no process spawning, so it composes with in-memory block replay.
  • The no-grad collection forwards, the iters=0 RTN/optimized-RTN searches, and the SignRoundV2 wrap-time init-scale searches all shard across the replicas too. AWQ scale search, GPTQ, and other calibration-fitting optimizers are not yet adapted and run serial, exactly as today.
  • Loss parity: the wrapped starting state is bit-identical to the serial run (checksum-verified) and the per-iteration gradient math is equivalent up to cross-device reduction order and bf16 transport; end-to-end quality is at parity (table below).
  • Per-iteration loss lines differ between serial and parallel runs: serial draws each iteration's batch from the full calibration pool while replicas draw from their disjoint shards. Both are reproducible per mode for a fixed seed; compare modes at the artifact level.
  • An explicit N raises with the blocking reasons if it cannot engage; auto shrinks to the devices that fit.
  • Each replica holds the full block mirror (bf16 weights + fp32 rounding values, gradients, best-MSE snapshot): ~12-13 GiB per GPU for 27B-class blocks (W4A16 g128, calibration 8x8192) at world=4 on 24 GB cards; host RAM peaks ~20-28 GB. Oversized blocks are declined by the VRAM guard with per-device reasons. A memory-sharded variant is future work.

Also: Transformers-v5 block-runner fixes (shared-cache rope kwargs arrive as per-batch (cos, sin) tuples, sliced per shard; inputs staged on the replica device), fail-visible CUDA peer-access enablement, opt-in AR_PERF_COUNTERS diagnostics.

Measured — Qwen3.8-27B (hybrid linear/full attention), W4A16 g128, iters=50, same seed and recipe, 4x RTX 3090:

config KL (protocol below) per-block tuning wall
serial (1 GPU) 0.02203 ~40-47 s
--parallel_quantization 4 0.021815 ~25-30 s

KL protocol: full-vocab fp32 KL vs the bf16 base, openwebtext 8x8192, same samples/seeds for both arms. Delta is within run noise.

At iters=0 (zero-shot optimized-RTN): 64-block run 13:00 -> 6:55 (1.9x; collection 3.5 -> 1.2 s, searches 5.2 -> 2.0 s per block, world=4). At iters>0 the wrap-time init-scale search drops 5.1 -> 1.9 s per block (~2.7x, GIL-limited) and per-replica compile lowers tune forward 72 -> 42 ms/iter.

Knobs: AR_TUNE_DDP_DEVICES, AR_PERF_COUNTERS (docs/environments.md).

Type of Change

New feature

Related Issues

Implements #2010 (multi-GPU quant parallelism), single-process flavor.

Independent of the pre-existing multi-process DDP integration for the LLM-Compressor workflow (most recently fixed in #1897): it is inert without an external launcher; this engine runs from the plain CLI/API and additionally shards the collection and search passes. The two lanes were not benchmarked against each other.

Checklist Before Submitting

  • My code has been tested locally.
  • Documentation has been updated as needed.
  • New or updated tests are included where applicable.
  • The CUDA CI has passed. You can trigger it by commenting /azp run Unit-Test-CUDA-AutoRound.

@AutoRoundBot

This comment has been minimized.

@avtc
avtc marked this pull request as draft September 11, 2026 20:43
@avtc
avtc force-pushed the feature/ddp-parallel-tuning branch from 849e278 to 230317f Compare September 11, 2026 22:20
@avtc
avtc marked this pull request as ready for review September 11, 2026 22:34
@AutoRoundBot

Copy link
Copy Markdown
Collaborator

/azp run Unit-Test-CUDA-AutoRound

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Single-process data-parallel tuning for block-wise quantization behind one flag: --parallel_quantization {off,auto,N} (default off). auto/N>=2 pin the replica world to the largest power-of-two <= visible CUDA devices, subject to a free-VRAM mirror guard.

- each block is mirrored onto the plan devices; replicas tune on disjoint calibration shards, so the effective batch matches the serial run
- gradients exchanged via bf16 transport + sign-cast for sign-SGD steps (bitwise-identical across replicas); in-process halving-doubling allreduce, no torchrun
- collection forwards, iters=0 RTN/OptRTN searches, and V2 wrap-time init-scale searches shard across the replicas too; AWQ/GPTQ not yet adapted and run serial
- losses: the wrapped starting state is bit-identical to serial (checksum-verified across independent runs);
  per-iteration loss lines differ because replicas draw from disjoint calibration shards (reproducible per mode
  for a fixed seed); end-to-end quality at parity: iters=50 KL 0.021815 (world=4) vs 0.02203 serial, within
  run noise
- explicit N raises with the blocking reasons if it cannot engage; auto shrinks to the devices that fit
- each replica holds a full block mirror: ~12-13 GiB/GPU for 27B-class blocks (W4A16 g128, calib 8x8192) at world=4; the VRAM guard declines oversized blocks with per-device reasons

Also: transformers-v5 fixes in the block runner (shared-cache rope kwargs arrive as per-batch (cos,sin) tuples, sliced per shard; inputs staged on the replica device); guarded excepts are fail-visible; AR_PERF_COUNTERS adds opt-in perf lines.

Knobs: AR_TUNE_DDP_DEVICES (docs/environments.md). Usage docs in docs/step_by_step.md + CN.

Tests: test/unit/test_cpu/quantization/test_ddp_core.py, test/unit/test_cuda/quantization/test_ddp_mirror.py.

Independent of the pre-existing multi-process DDP integration for the LLM-Compressor workflow (intel#1897): that one is inert from the plain CLI; this engine is single-process and additionally shards the collection passes and the zero-shot/wrap-time searches.

CI fixes (build 75613, unit suite on the previous push): the tune-loop
surgery had dropped the upstream loop-tail pair that records the iter-0
loss, so the end-of-block summary formatted None and failed 93 iters>0
tests; the aborted-block leftovers then cascaded into the four
WrapperLinear.linear_forward failures when the calibration restore sweep
met still-wrapped modules. Restores the pair verbatim, adds an AST
contract test pinning the assignment inside the loop, and removes a
duplicate P2P ordering test flagged by ruff.

P2P enablement removed after a measured no-delta A/B on the validation
rig (27B, iters=10, ddp4): per-block walls 18.4/12.6/12.2s with explicit
enablement vs 18.9/12.6/12.0s with it skipped, gradient-exchange means
sub-20ms both ways -- the fabric's cross-device copies ride the memcpy
path regardless, so explicit peer-access setup bought nothing. The
AR_TUNE_DISABLE_P2P knob, the cudart binding/signature machinery, and
their tests are gone with it.

Signed-off-by: avtc <tarasenkov@gmail.com>
@avtc
avtc force-pushed the feature/ddp-parallel-tuning branch from 230317f to b0533cc Compare September 12, 2026 10:37
@AutoRoundBot

Copy link
Copy Markdown
Collaborator

/azp run Unit-Test-CUDA-AutoRound

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@avtc
avtc requested a review from wenhuach21 September 12, 2026 13:22
@wenhuach21 wenhuach21 added this to the 0.16.0 milestone Sep 13, 2026
@wenhuach21

Copy link
Copy Markdown
Contributor

Thanks for this PR. This is exactly what we need right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants