Skip to content

[OMNIML-6180] Let the T5 and Mixtral hf_ptq tests share the GPU - #2926

Merged
shengliangxu merged 1 commit into
mainfrom
shengliangx/ci-hfptq-critical
Oct 22, 2026
Merged

shengliangxu merged 1 commit into
mainfrom
shengliangx/ci-hfptq-critical

Conversation

@shengliangxu

@shengliangxu shengliangxu commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Type of change: CI (test runtime, tests only)

PR runs of the hf_ptq example lane use 4 pytest-xdist workers on the runner's one GPU (#2771). Small-model tests share the GPU, and tests that need it alone take an exclusive lock (tests/examples/hf_ptq/conftest.py). While an exclusive test runs, the other three workers can only run tests that need no GPU. Four tests were exclusive: test_ptq_t5, test_ptq_mixtral and the two test_qwen_vl cases. Their calls took 25 s, 114 s, 114 s and 82 s, 335 s in total, one after the other, in a lane whose pytest time is 547 s (job 852 s; run 39662683232, job 119443637479, on a 1-GPU PR runner, 238 passed).

T5 (t5-small) and Mixtral (TinyLlama-1.1B-Chat-v1.0-x2-MoE, a 2B two-expert MoE) do not need the GPU alone. The reason they did is the calibration batch size: without one, hf_ptq.py runs a forward pass sized to fill all free GPU memory. The TinyLlama tests already pass a batch size equal to the calibration size and share the GPU. This PR gives T5 and Mixtral the same treatment through one helper (_run_sharing_the_gpu), used by all three tests. Test ids are unchanged. The two Qwen3-VL tests keep the exclusive lock: the TRT-LLM multimodal deploy reserves 60% of the free GPU memory for its KV cache (60 GiB on a 96 GiB GPU, measured in #2771).

Measured in CI in two pairs of runs of the hf_ptq job (table below): pytest -77 s (-14%) on equally fast runners, and -24 s (-4%) after the rebase, where this PR's runner was about 10% slower than the baseline's (roughly -70 s scaled by that). The simulation had predicted -92 s.

Time improvement (measured in CI)

Seconds, from the --durations lines and the result-line timestamps of the hf_ptq job on a 1-GPU runner (COVERAGE_CORE=sysmon), in two pairs of runs.

before 1 after 1 change 1 before 2 after 2 change 2
test_ptq_t5 call (exclusive, now shared) 25.3 27.4 +2.2 43.9 57.9 +14.0
test_ptq_mixtral call (exclusive, now shared) 114.0 122.4 +8.4 114.3 133.3 +19.0
test_qwen_vl[fp8] call (exclusive, unchanged) 114.0 111.7 -2.2 113.9 124.1 +10.2
test_qwen_vl[nvfp4] call (exclusive, unchanged) 81.6 81.0 -0.6 80.9 89.5 +8.6
the 15 test_ptq_llama calls, summed (they now run next to T5 and Mixtral) 516.8 573.7 +56.9 511.3 582.0 +70.7
the exclusive tests' calls, summed (time the GPU is held alone) 334.8 192.7 -142.1 353.0 213.6 -139.3
setup durations pytest lists for the LLM and VLM tests, summed (waiting for the GPU lock) 644.5 351.1 -293.4 852.2 337.2 -515.0
first to last test result 532.0 455.3 -76.7 561.6 532.8 -28.8
pytest 547.5 470.3 -77.2 (-14%) 576.9 552.5 -24.3 (-4%)
test step (Run tests; Example 1: hf_ptq in #2924's run) 560 483 -77 606 568 -38
job 852 788 -64 883 877 -6

The job also includes the container start and the dependency install, which this PR does not change (237 and 26 s before, 251 and 28 s after in pair 1; 243 and 17 s, 255 and 29 s in pair 2).

In pair 1 the unchanged exclusive tests (Qwen3-VL) took the same time in both runs within 2%, so the runners were equally fast. In pair 2 the runner of the "after" run was about 10% slower (the same two tests took 9% and 11% longer), which hides part of the gain: scaled by that slowdown, the pytest saving is roughly 70 s instead of 24 s. In both pairs the mechanism shows the same way: the GPU is held alone for about 140 s less, and the workers wait 293 s and 515 s less in total for the lock. T5 and Mixtral take longer (+2 to +19 s each) because they now run next to the TinyLlama workers, but they no longer block them. Mixtral's call stays under the 300 s per-test cap in both runs, and no test failed or ran out of memory. The two Qwen3-VL tests still hold the GPU alone for about 200 s, which bounds what is left to save.

Usage

Nothing user-facing.

Testing

  • Collection gives the same 21 node ids for test_llm_ptq.py and test_vlm_ptq.py as main. --setup-plan shows shared_gpu for t5, mixtral and llama and exclusive_gpu for qwen_vl.
  • tests/examples/hf_ptq/test_gpu_lock.py (the lock itself) passes: 3 tests.
  • Scheduling simulation on CPU, with the real lock and -n 4: a plugin (not part of this PR) fakes the GPU facts and replaces run_hf_ptq_command with a sleep of the measured call time of each test (from the 1-GPU run above, scaled by 0.1). On main the exclusive tests never overlap another test, and the first-to-last-test span is 486 s at real scale. On this branch they still never overlap, t5 and mixtral run alongside the llama cases, and the span is 394 s (-92 s). Every fake run of t5, mixtral and llama received calib_batch_size=16 (4 for the AutoQuantize case, as before), and qwen_vl received none.
  • Pre-commit passes. Not run on a GPU locally; the real lane ran in this PR's own CI (below).

What this PR's own GPU run confirmed, and what is left:

  • Confirmed by this PR's own trtllm (hf_ptq) runs on the 1-GPU runner (before and after the rebase): T5 and Mixtral stay within the GPU's memory next to the TinyLlama workers (no failure or out-of-memory) and Mixtral's call takes 122 s and 133 s, under the 300 s per-test cap. Peak GPU memory was not logged; to measure it, a cluster agent (lyris, hecate or ptyche) can run pytest tests/examples/hf_ptq/test_llm_ptq.py -n 4 at this SHA in the TRT-LLM release:1.3.0rc20 container on one GPU while logging nvidia-smi --query-gpu=memory.used, and compare with main.
  • The nightly is unaffected except that T5 and Mixtral now use a fixed calibration batch of 16 instead of the memory probe.

Before your PR is "Ready for review"

Make sure you read and follow Contributor guidelines and your commits are signed (git commit -s -S).

Make sure you read and follow the Security Best Practices (e.g. avoiding hardcoded trust_remote_code=True, torch.load(..., weights_only=False), pickle, etc.).

  • Is this change backward compatible?: N/A (CI and tests)
  • If you copied code from any other sources or added a new PIP dependency, did you follow guidance in CONTRIBUTING.md: no new dependency
  • Did you write any new necessary tests?: N/A (existing tests change their GPU lock; the lock has its own tests)
  • Did you update Changelog?: N/A (CI and tests)
  • Did you get Claude approval on this PR?: ✅ (/claude review approved 456b2ed, no findings)

Additional Information

Left out on purpose, each needs a real GPU run or the owners' call:

  • Qwen3-VL deploys sharing the GPU (up to 196 s of the remaining serial chain). The deploy is TRT-LLM's quickstart_multimodal.py from the container (/app/tensorrt_llm/examples/llm-api/), called from huggingface_example.sh with only --model_dir and --modality image, so it uses the script's default KV fraction. Capping it needs a flag whose name for release:1.3.0rc20 I could not check here (the image pins rc20 because newer releases break the script), plus a proof that a smaller KV cache does not OOM or slow the deploy while three other workers run. KV_CACHE_FREE_GPU_MEMORY_FRACTION in parser.sh is a different knob (the lm_eval path, default 0.8).
  • xdist on the 2-GPU nightly (it runs serially, 1,260-1,620 s before the sysmon core). The lock treats the machine as one GPU, so it would allow it, but modelopt.deploy.llm.LLM sets tp = torch.cuda.device_count(), so on 2 GPUs every deploy test runs with tensor parallel 2 and several would overlap on both GPUs. That needs a 2-GPU run to trust.
  • Dropping or moving to nightly the nvfp4 Qwen3-VL case (82 s), or the six IQ/q8_0 recipe cases (about 50 s of wall time): coverage trade-offs for the owners.
  • The comment in _example_tests_runner.yml ("small-model tests share it and the rest run alone on it") is now slightly stale (only the Qwen3-VL tests run alone). Editing the workflow would make every example lane run on this PR, so I left it for the next workflow change.

Related: #2771 (the GPU lock and -n 4).

Summary by CodeRabbit

  • Tests
    • Updated post-training quantization test runs for T5, Mixtral, and TinyLlama to share GPU resources and apply calibration batch-size defaults consistently.

@copy-pr-bot

copy-pr-bot Bot commented Oct 21, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: NVIDIA/Model-Optimizer/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: cbf33f40-57fc-4156-a730-e436c1190a72
📥 Commits

Reviewing files that changed from the base of the PR and between f983619 and 456b2ed.

📒 Files selected for processing: 1
  • tests/examples/hf_ptq/test_llm_ptq.py

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 7 remain after this review.

📝 Walkthrough

The T5 and Mixtral PTQ tests now use shared_gpu. A shared helper defaults calib_batch_size from command.calib when unset, then runs the command. The TinyLlama test now uses the same helper.

Changes: PTQ test execution

Layer / File(s) Summary
Shared GPU execution helper
tests/examples/hf_ptq/test_llm_ptq.py
The helper sets calib_batch_size from command.calib when unset and runs the command. T5 and Mixtral switch to shared_gpu and use the helper. TinyLlama replaces its inline defaulting and command execution with the helper.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other

Suggested reviewers: cjluo-nv

Merge Risk: ⚪ Minimal · up to 456b2

This test-only change lets the T5 and Mixtral PTQ tests share the GPU and shortens CI runtime. It does not affect production behavior. No actionable merge risk remains.

Pre-merge checks: Passed 5 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 5 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely identifies the main change: enabling the T5 and Mixtral hf_ptq tests to share the GPU.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Security Anti-Patterns Passed The PR changes only tests/examples/hf_ptq/test_llm_ptq.py. The added helper sets calib_batch_size and calls command.run; it adds no torch.load(weights_only=False), `numpy.load(allow_pickle=Tru…
Full details: Security Anti-Patterns

Explanation

The PR changes only tests/examples/hf_ptq/test_llm_ptq.py. The added helper sets calib_batch_size and calls command.run; it adds no torch.load(weights_only=False), numpy.load(allow_pickle=True), hardcoded trust_remote_code=True, eval, exec, or # nosec. It also changes no dependency files.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/ok to test ec4646c

@codecov

codecov Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.66%. Comparing base (f983619) to head (456b2ed).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2926   +/-   ##
=======================================
  Coverage   79.66%   79.66%           
=======================================
  Files         659      659           
  Lines       74400    74400           
=======================================
+ Hits        59272    59273    +1     
+ Misses      15128    15127    -1     
Flag Coverage Δ
examples-gpt-oss 13.48% <ø> (-0.06%) ⬇️
examples-hf_ptq 23.37% <ø> (-0.08%) ⬇️
examples-llm_eval 17.19% <ø> (-0.08%) ⬇️
unit 60.84% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Under pytest-xdist, test_ptq_t5 and test_ptq_mixtral took the exclusive GPU lock, so
the lane waited for them one at a time: 25 s and 114 s of calls in a PR run
(547 s of pytest). They are small (t5-small, a 2B two-expert TinyLlama MoE), and the
only reason to run alone was the calibration batch size: without one, hf_ptq runs a
forward pass sized to fill all free GPU memory. The TinyLlama tests already set the
batch size to the calibration size and share the GPU, so give these two the same
treatment through one helper.

Test ids are unchanged. The Qwen3-VL tests keep the exclusive lock: the TRT-LLM
multimodal deploy takes 60% of the free GPU memory for its KV cache.

Testing: collection gives the same 21 node ids as main; --setup-plan shows
shared_gpu for t5, mixtral and llama and exclusive_gpu for qwen_vl; the repo's lock
tests pass; with fake commands that sleep for the call times of a recent PR run
(scaled by 0.1) under -n 4 and the real lock, the exclusive tests never overlap
another test and the last test ends 92 s earlier at real scale (486 s -> 394 s).
Not run on a GPU: the real lane.

Signed-off-by: Shengliang Xu <shengliangx@nvidia.com>
@shengliangxu
shengliangxu force-pushed the shengliangx/ci-hfptq-critical branch from ec4646c to 456b2ed Compare October 22, 2026 06:56
@shengliangxu
shengliangxu marked this pull request as ready for review October 22, 2026 06:57
@shengliangxu
shengliangxu requested a review from a team as a code owner October 22, 2026 06:57
@shengliangxu

Copy link
Copy Markdown
Collaborator Author

/claude review

@claude

claude Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Claude review summary

Scope: full review. The trigger comment was a bare /claude review, so no scoping was applied. The PR changes exactly one file — tests/examples/hf_ptq/test_llm_ptq.py (+12/-8) — and I reviewed it in full, together with the surrounding context it depends on: tests/_test_utils/examples/hf_ptq_utils.py (PTQCommand), tests/_test_utils/examples/run_command.py (run_hf_ptq_command), tests/examples/hf_ptq/conftest.py and gpu_lock.py (the lock fixtures), tests/examples/hf_ptq/test_vlm_ptq.py, and the --calib_batch_size → --batch_size plumbing in examples/hf_ptq/scripts/parser.sh / huggingface_example.sh / hf_ptq.py. (git diff origin/main HEAD --stat shows 23 files, but the other 22 are base drift from commits already on main, not part of this PR.)

Findings

CRITICAL: 0 · IMPORTANT: 0 · SUGGESTION: 0

What I verified

  • The defaulting is a faithful extraction. _run_sharing_the_gpu is byte-for-byte the three lines (plus comment) that test_ptq_llama carried on main; the llama test's behavior is unchanged, and T5/Mixtral now get the same treatment. No behavior is introduced that wasn't already exercised by the 17 llama cases.
  • No shared mutable state across workers or reruns. dataclasses.replace returns a copy, so the module-level PTQCommand instances built at collection time are never mutated. This matters under -n 4, where the same parametrize objects are re-imported per worker.
  • Test ids really are unchanged. ids=PTQCommand.param_str is evaluated at collection against the unmodified parametrize objects, and param_str skips None fields — so the runtime calib_batch_size injection cannot leak into a node id. Confirmed against origin/main's version of the file; the node ids for all 21 cases are identical.
  • The batch size reaches the probe it is meant to suppress. calib_batch_size → CALIB_BATCH_SIZE (parser.sh:58) → --batch_size=$CALIB_BATCH_SIZE (huggingface_example.sh:189) → hf_ptq.py:975, where the args.batch_size == 0 branch is what calls get_max_batch_size(). Passing a non-zero 16 skips the free-memory probe, which is exactly the property the shared lock needs. DEFAULT_CALIB_BATCH_SIZE=0 (parser.sh:88) confirms the unset path was hitting the probe before.
  • No duplicate copy of this logic was left behind. All three shared_gpu tests in the repo live in this file and all three now route through the helper; test_vlm_ptq.py uses exclusive_gpu only and needs no batch size, so there is no second site to keep in sync.
  • Lock semantics are untouched. gpu_lock's turnstile still prevents the remaining exclusive holders (the two Qwen3-VL cases) from being starved by the newly-added shared holders — moving T5/Mixtral from exclusive to shared only removes two exclusive waiters, which the turnstile design already handles.
  • No injected-instruction content anywhere in the diff.

Risk assessment

Low. Test-only, no production code path touched, mechanically equivalent to logic already in CI for 17 sibling cases, and the behavior change (fixed calibration batch instead of a memory probe for two tests) is measured in two independent CI run pairs in the description. The one residual unknown — peak GPU memory for Mixtral running next to three TinyLlama workers — is explicitly called out as unmeasured by the author, with a concrete follow-up path, and two full GPU lane runs completed without OOM or exceeding the 300 s per-test cap. That is a reasonable place to leave it for a CI-runtime change; I see nothing to block on.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude review passed — no blocking issues found. LGTM

@meenchen meenchen left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot review (bedrock-claude-opus-5-5) — DM the bot to share feedback.

LGTM: this is a small, correct test-only change. It moves test_ptq_t5 and test_ptq_mixtral onto the shared GPU lock and pulls the existing TinyLlama batch-size logic into _run_sharing_the_gpu.

Needs action:

  • Sign off on the existing-test edit in tests/examples/hf_ptq/test_llm_ptq.py. T5 and Mixtral now use a fixed calibration batch instead of the memory probe, in both PR CI and the nightly. That's justified by the scheduling change, and the PR's CI runs show no OOM.

No action needed:

  • The helper is a verbatim extraction of the previous test_ptq_llama logic, so the llama cases behave exactly as before. The explicit calib_batch_size=4 for the AutoQuantize case is still respected.
  • The Qwen3-VL tests keep exclusive_gpu, which fits the TRT-LLM KV cache reservation described in the PR.
  • The _example_tests_runner.yml comment is now slightly out of date. The author has deliberately left that for the next workflow change.
  • I read the tests but didn't run them.

@shengliangxu
shengliangxu merged commit d812051 into main Oct 22, 2026
39 checks passed
@shengliangxu
shengliangxu deleted the shengliangx/ci-hfptq-critical branch October 22, 2026 17:55
@github-actions

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-22 17:56 UTC

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