Skip to content

fix(engine-cuda): bound Qwen3 shape-plan cache with a 2-entry LRU - #16

Open
Qiiks wants to merge 1 commit into
cortexkit:masterfrom
Qiiks:feat/qwen3-shape-lru-cache
Open

Qiiks wants to merge 1 commit into
cortexkit:masterfrom
Qiiks:feat/qwen3-shape-lru-cache

Conversation

@Qiiks

@Qiiks Qiiks commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Problem

QwenContext retains every distinct (batch, seq) ShapePlan for the worker's lifetime. Each plan owns a persistent arena (scales with batch*seq*hidden + batch*heads*seq^2, see #2314-style arithmetic), up to 64 MiB of cuBLASLt workspace, a cudaGraph and a cudaGraphExec. A long-lived worker that embeds diverse batch shapes therefore accumulates one arena per distinct shape.

Observed live: the production gateway serving AFT/MC traffic logged repeated cudaMalloc ... out of memory engine crashes (cuda_family_common.cuh:73) after accumulating shapes like 64x172 (arena 646 MB), 16x1117 (1.59 GB), and dozens of 1xN shapes — on a 6 GiB RTX 4050, where persistent f16 weights alone are ~1.1 GiB.

Fix

Bound the cache: retain at most two warm plans per context (max_plans = 2, LRU order).

  • Evict before allocate: a cache miss with a full cache evicts the LRU victim before allocating the new arena, so a third full arena never raises the peak.
  • Evict while idle: eviction happens after cudaStreamSynchronize on the context's single stream, so victim buffers are freed while no kernel references them; the just-executed plan is promoted to MRU and never the victim.
  • RAII teardown: erasing a map entry destroys the unique_ptr<ShapePlan>, whose destructor chain frees graph exec, graph, and every DeviceAllocation (cudaFree). Eviction is what bounds VRAM.
  • Also restores the plans member declaration that the eviction edit had dropped (the tree previously failed to compile with 7 undefined-identifier errors).

Verification (live RTX 4050, production gateway lane)

  • Full release build of synapse-worker-cuda (--features cuda) green.
  • Four distinct shapes (1x34, 1x66, 1x98, 1x130) each captured a plan (captured_exact=true in worker logs).
  • Replay of the evicted first shape after the fourth returned a bit-identical vector (max abs delta 0.0), norms all 1.0 — correctness preserved across eviction.
  • Steady serving VRAM ~1.9 GiB with no growth across shape churn (previously unbounded, ultimately OOM-crashing).

Notes


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Bounds the Qwen3 shape-plan cache to two entries with LRU eviction, preventing VRAM exhaustion on workers that see many distinct batch shapes.

  • Evicts the least-recently-used plan before allocating a new one, after the CUDA stream is idle, so no kernel references the freed buffers.
  • Restores the plans member declaration that was accidentally dropped, fixing a compile error.

Written for commit d409db1. Summary will update on new commits.

Review in cubic

Every distinct (batch,seq) ShapePlan allocates a persistent arena plus
up to 64 MiB of cuBLASLt workspace, a cudaGraph and a cudaGraphExec,
retained for the worker's lifetime. A long-lived worker embedding
diverse batch shapes therefore accumulated one arena per shape and
could OOM the 6 GiB RTX 4050 (observed out-of-memory crashes in the
live gateway log at cuda_family_common.cuh:73).

Retain at most two warm plans per context. Eviction happens before
allocation of a new plan and after cudaStreamSynchronize, so a victim's
buffers are freed while no kernel references them; the just-executed
plan is always promoted to most-recently-used and never the victim.
Deleting a plan destroys its DeviceAllocation members (cudaFree) via
destructors, so eviction is what bounds VRAM.

Also restores the plans member declaration that the eviction edit had
dropped (build previously failed with 7 undefined-identifier errors).
Verified live: four distinct shapes captured, replay of the evicted
first shape bit-identical (max_abs_delta=0), steady serving VRAM
~1.9 GiB on the RTX 4050 lane.
Copilot AI lite review requested due to automatic review settings September 17, 2026 00:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 1 file

Re-trigger cubic

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.

2 participants