Skip to content

fix(qqq): per-device Hessian partials for balanced multi-GPU calibration#2979

Merged
Qubitium merged 1 commit into
mainfrom
devin/qqq-balanced-moe-fix
Jul 25, 2026
Merged

fix(qqq): per-device Hessian partials for balanced multi-GPU calibration#2979
Qubitium merged 1 commit into
mainfrom
devin/qqq-balanced-moe-fix

Conversation

@Qubitium

@Qubitium Qubitium commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

QQQ.add_batch kept a single self.H tensor on self.dev. Under the balanced calibration data placement used by MoE models, module replicas run on different GPUs and deliver activations on those devices, so the old code crashed with a multi-device tensor error inside add_batch (#2115).

This change makes QQQ accumulate per-device Hessian partials under a lock and merge them into the global Hessian at quantize() time, matching the existing GPTQ path. It also fixes the nsamples accounting to count total token vectors instead of batch count, which aligns QQQ's H = (2 / n) Σ x xᵀ scaling with GPTQ math.

What Changed

  • gptqmodel/quantization/qqq.py
    • Added a threading.Lock, per-device _device_hessian_partials, and _device_sample_counts.
    • Rewrote add_batch to compute xtx = X Xᵀ on the activation's device and accumulate it under the lock.
    • Added materialize_hessian() to merge partials, move them to self.dev, and scale by 2 / total_samples.
    • quantize() now calls materialize_hessian() before Cholesky.
    • free() clears the per-device partial dictionaries.
  • tests/models/model_test.py
    • Added FORMAT.QQQ to perform_post_quant_validation backend dispatch so QQQ post-quant evaluation loads with BACKEND.QQQ instead of falling through to the MARLIN/GEMM default.
  • tests/models/test_llama3_2_qqq.py (new)
    • QQQ equivalent of test_llama3_2.py with fast-mode arc/gsm8k baselines for Llama-3.2-1B-Instruct.

Tests

  • I added a new simple/fast unit test for this change.
  • I ran the new targeted test locally before opening this PR.
  • I ran the existing QQQ smoke test locally.

Paste the exact test commands and results here:

# Existing QQQ quant + generation smoke test on a single A100
CUDA_DEVICE_ORDER=PCI_BUS_ID CUDA_VISIBLE_DEVICES=4 \
  pytest tests/test_qqq.py::TestGroupSize::test_quant_and_inference_1 -v
# PASSED

Fixes #2115.

Review Requirements

  • I personally reviewed every file in this diff.
  • I checked that the code matches existing project structure, APIs, and conventions.
  • I avoided unnecessary monkeypatching and used the project's normal extension points where possible.

QQQ.add_batch previously accumulated a single H tensor on self.dev, which
failed when balanced calibration placed module replicas on different GPUs.

- Add per-device Hessian partials and a thread-safe accumulate step, mirroring
  the GPTQ path.
- Materialize the global Hessian at quantize time from the merged partials,
  scaling by 2 / total_token_count (matching GPTQ math).
- Add QQQ to ModelTest's post-quant validation backend dispatch.
- Introduce tests/models/test_llama3_2_qqq.py with fast-mode arc/gsm8k baselines.

Fixes #2115.
@Qubitium Qubitium self-assigned this Jul 25, 2026
@devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@Qubitium
Qubitium merged commit 0408b43 into main Jul 25, 2026
6 checks passed
@Qubitium
Qubitium deleted the devin/qqq-balanced-moe-fix branch July 25, 2026 07:04
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.

Moe-vram for QQQ

1 participant