Reactor scanner: one fixed spin count cannot serve both long waits and fast completions
Maintainers usually reply within 2 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- rust
- Domain
- embedded-iot, performance
Research direction
Read the cuda_async::spin_budget implementation and the ignored ab_spin_budget benchmark added by #296, then compare the reported model results with a real-GPU A/B run on a quiet host. The issue leaves the default-policy decision open; done means evidence supports a decision on the default and the related configuration questions.
Written by the indexing model from the issue text.
Description
Migrated from NVlabs/cutile-rs#297, opened by @0z5a on 2026-09-18. 1 comment remain on the original.
Problem
The reactor scanner's idle behavior is a single fixed pass count — SPIN_PASSES = 10_000 — before it falls back to yielding. One constant cannot serve both regimes the scanner meets, and both occur in the same process:
- Long wait (a millisecond-scale kernel, or a stalled stream): spinning burns a core for no benefit, because nothing is going to land during that window.
- Fast completions (thousands of small completions): yielding adds a scheduler round-trip to a waker that would otherwise fire immediately.
Tuned for latency the scanner burns a core for the whole duration of a long kernel; tuned for CPU it adds latency to every fast completion. Because the same constant serves both, the current code pays both costs rather than trading them.
Measurement
#296 adds cuda_async::spin_budget with two policies — Fixed { passes } (the current behavior) and Adaptive { min, max }, which grows the budget toward max when a completion lands and halves it toward min when a full budget expires with nothing landed — plus an ignored A/B bench in the same module, following the crate's existing ab_bench convention.
The bench models a strict ping-pong: one completion in flight, a device that sleeps gap then writes that slot's flag, and a scanner running the reactor's spin/yield loop.
cargo test -p cuda-async --release --lib ab_spin_budget -- --nocapture --ignored
| workload | policy | spins | yields | lat p50 | lat p95 |
|---|---|---|---|---|---|
| fast (10us) | fixed 10000 | 409,422 | 0 | 454 ns | 716 ns |
| fast (10us) | adaptive | 25,336 | 39,674 | 330 ns | 481 ns |
| slow (1ms) | fixed 10000 | 1,999,800 | 510,476 | 352 ns | 1,067,764 ns |
| slow (1ms) | adaptive | 25,336 | 679,230 | 493 ns | 1,064,272 ns |
On the regime the policy targets — a long wait — it cuts spin work 79x at an unchanged tail latency (p95 1.0678 ms vs 1.0643 ms). Spin passes are a deterministic proxy for CPU burn: what the scanner spends before yielding. The fast regime is unchanged or better.
What is actually open here
The open question is the default, not the mechanism. #296 ships Adaptive as opt-in via CUDA_ASYNC_SPIN=adaptive and deliberately leaves the default at Fixed:
- The fast-regime p50 moves within run-to-run noise on a shared host, so p50 is not strong enough evidence to claim a strict win in that regime. p95 is the meaningful latency number here.
- The bench is a model, not a real kernel workload. Deciding the default wants a real-GPU A/B on a quiet host.
Related shape questions left open: whether to drop the env switch in favor of always-adaptive, whether the floor should be configurable, and whether the growth/halving ratio should be tunable.
- Dominant language
- Rust
- Stars
- 3.8k
- Forks
- 325
- Avg merge
- 5d 21h
- Merged PRs (30d)
- 67
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from NVIDIA/cuda-rust
-
cutile-rs supply-chain
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Maintainers usually reply within 2 days
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
NVIDIA/cuda-rust#1568 · 1 comment ·
Maintainers usually reply within 2 days
-
[BUG]: The doc of trait `LoadTileLike` is incorrectMay be free again @akhil9tiet claimed this 9 days ago, and no pull request is open. Openbug
Difficulty 1/5 Under an hour Newbie friendliness 72/100
NVIDIA/cuda-rust#1523 · 2 comments ·
Maintainers usually reply within 2 days
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 2 days
All issues in NVIDIA/cuda-rust
Similar issues
-
bug easy good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
lacs-project/sysknife#659 ·
Maintainers usually reply within 2 days
-
E_FIT_INPUT_MISSING (mixture overrides): the message says ferx-r bundles lack mixture_overridesOpenP3
Difficulty 1/5 Under an hour Newbie friendliness 83/100
Maintainers usually reply within 1 day
-
documentation
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
registrystack/registry-stack#2431 ·
Maintainers usually reply within 1 day
-
contribution
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
farion1231/cc-switch#8863 · 1 comment ·
Maintainers usually reply within 1 day