feat(runtime): always-on TRB temporary variable buffer (internal, no user switch)#1198
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughAdds ChangesTRB Serial Tensor Buffer Pool Plan
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces an implementation plan for a TRB Temporary Variable Buffer to optimize memory allocation overhead. The review feedback highlights three key areas for improvement: simplifying the cleanup contract by leveraging the existing validate_runtime_impl gateway, resolving a design contradiction between the aggregate budget contract and segmented chunk allocation, and adding a lightweight active-run guard to prevent silent data corruption from concurrent runs.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
docs/trb-serial-tensor-buffer-pool-plan.md (3)
11-11: 📐 Maintainability & Code Quality | 🔵 TrivialConsider using English consistently throughout the document.
Line 11 uses Chinese characters "临时变量" while the rest of the document is entirely in English. For consistency and to avoid encoding issues in some toolchains, consider using only English: "This plan uses 'temporary variable buffer' for the same concept as 'linshi biancun buffer'."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/trb-serial-tensor-buffer-pool-plan.md` at line 11, The document mixes Chinese and English, so update the referenced text in the plan to use English consistently. Replace the Chinese phrase in the buffer description with an English equivalent in the same section of docs/trb-serial-tensor-buffer-pool-plan.md, keeping the wording aligned with the existing terminology used elsewhere in the document.
154-157: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winClarify finalize cleanup ordering when a run is active.
The text says to "log it, release retained chunks" if finalize sees an active run. For defensive correctness, explicitly state whether
end_temporary_buffer_run()should be called beforeclear()to reset theactive_flag, or ifclear()alone is sufficient because the runner is being destroyed. This prevents implementers from leaving the flag in an inconsistent state if any post-finalize diagnostics check it.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/trb-serial-tensor-buffer-pool-plan.md` around lines 154 - 157, Clarify the finalize cleanup order in finalize_common()/sim finalize when an active temporary-buffer run is present: specify whether end_temporary_buffer_run() must be called before clear() to reset active_, or whether clear() alone is sufficient because the runner is being torn down. Update the contract wording so implementers know how to handle the active run state consistently and avoid leaving diagnostics-visible flags stale.
526-552: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd unit tests for configuration edge cases.
Consider adding focused unit tests for:
configure_temporary_bufferwith same budget twice is a no-op (no reallocation);configure_temporary_bufferwhile a run is active fails with clear error;begin_temporary_buffer_runfailure path (e.g., OOM during chunk allocation) is handled correctly.These complement the existing test list and guard against reconfiguration bugs.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/trb-serial-tensor-buffer-pool-plan.md` around lines 526 - 552, Add focused unit tests for the temporary-buffer configuration edge cases: verify configure_temporary_buffer is a no-op when called twice with the same budget, verify configure_temporary_buffer rejects changes while a run is active with a clear error, and verify begin_temporary_buffer_run handles allocation failure/OOM correctly. Place these alongside the existing buffer unit tests and use the same temporary-buffer pool APIs and run lifecycle symbols so the new coverage matches the current single-active-run model.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/trb-serial-tensor-buffer-pool-plan.md`:
- Around line 448-460: The bind pseudocode currently assumes
begin_temporary_buffer_run() always succeeds and sets temp_run_active=true
unconditionally, but the HostApi callback returns a bool. Update the bind flow
to check the return value from begin_temporary_buffer_run() and fail the bind
path immediately with a clear error if it returns false, before any TensorLease
recording or device memory work; keep temp_run_active=true only after a
successful begin_temporary_buffer_run() call.
---
Nitpick comments:
In `@docs/trb-serial-tensor-buffer-pool-plan.md`:
- Line 11: The document mixes Chinese and English, so update the referenced text
in the plan to use English consistently. Replace the Chinese phrase in the
buffer description with an English equivalent in the same section of
docs/trb-serial-tensor-buffer-pool-plan.md, keeping the wording aligned with the
existing terminology used elsewhere in the document.
- Around line 154-157: Clarify the finalize cleanup order in
finalize_common()/sim finalize when an active temporary-buffer run is present:
specify whether end_temporary_buffer_run() must be called before clear() to
reset active_, or whether clear() alone is sufficient because the runner is
being torn down. Update the contract wording so implementers know how to handle
the active run state consistently and avoid leaving diagnostics-visible flags
stale.
- Around line 526-552: Add focused unit tests for the temporary-buffer
configuration edge cases: verify configure_temporary_buffer is a no-op when
called twice with the same budget, verify configure_temporary_buffer rejects
changes while a run is active with a clear error, and verify
begin_temporary_buffer_run handles allocation failure/OOM correctly. Place these
alongside the existing buffer unit tests and use the same temporary-buffer pool
APIs and run lifecycle symbols so the new coverage matches the current
single-active-run model.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e992fafc-1d81-49ff-a3d7-3cea3aeb9bfd
📒 Files selected for processing (1)
docs/trb-serial-tensor-buffer-pool-plan.md
befb5c5 to
3bf8392
Compare
Two things: (1) replace explicit budget with a self-sizing AUTO buffer, (2) title/body vs. actual diff1. Reconsider the core Decision: drop the explicit budget, make the buffer self-sizing. This is a direction-level suggestion, not a tweak — it changes the plan's Decision, so flagging it up front. The current design pushes model-shape knowledge (hidden size, vocab pad, max batch/token) onto the serving/runner owner via Concretely:
I want to be honest about what this gives up, because these were presumably why you chose explicit budget:
The upside is that "zero-config, just make the churn go away" is a real product win, and it keeps model-shape knowledge out of the runtime entirely — which the plan already lists as a goal. 2. Title/body vs. diff. The PR says "documentation-only... Not run", but the diff carries ~2400 lines of implementation + C++/Python UTs beyond the 592-line plan doc. Those tests should be actually run / CI-green before merge, and the title probably wants |
Re-review after the AUTO rework — looks good, two loose endsThe AUTO switch landed well, and the Two loose ends before merge:
Neither is a design issue — the mechanism itself is in good shape now. |
|
Two more cleanups, both about "make it the cleanest version": 1. Drop the
if "max_temporary_buffer_bytes" in config:
raise ValueError("max_temporary_buffer_bytes has been removed; use temporary_buffer_mode='auto'")plus its UT in 2. I checked the CANN 9.0.0 runtime headers: the only device-memory primitives are Neither blocks the design — both are polish toward the minimal/cleanest form. |
ebce56d to
1f72a37
Compare
6ee7a45 to
59931b1
Compare
|
Pushed a commit directly (maintainer edit, Rationale: the AUTO buffer is always result-equivalent to the old per-run malloc/free path — only faster — and TRB runs are already serial per runner (the static arena pool enforces this), so there was no correctness reason to gate it behind opt-in. Exposing it through Python / pybind / C-ABI / ChipWorker pushed an internal allocation decision up the whole stack for no benefit. Removed: Docs (RUNTIME_LOGIC.md §2.4, task-flow.md) and tests retargeted to the always-on behavior; OFF-path test coverage now nulls the callbacks instead of toggling an enable flag. Verified locally: a2a3+a5 sim+onboard runtimes build clean; Python UT 92 passed; trb |
|
Pushed a follow-up maintainer commit ( The prior commit kept a ~330-line
Net −442 lines on top of the previous commit. No behavior change — same always-on retained-buffer reuse, just without the allocator-class indirection. Verified: a2a3+a5 sim+onboard build clean; Python UT 92 passed; |
73e85d5 to
2073441
Compare
Cut the per-run device_malloc / device_free of ordinary non-child tensors on
the tensormap_and_ringbuffer (TRB) bind path. TRB now stages them through a
single runner-scoped retained buffer that grows to the high-water packed size
and is reused across runs; steady-state (stable decode shapes) converges to
zero temporary allocations.
This is an internal allocation optimization with no user-facing switch — it is
always on for TRB and always result-equivalent to the old malloc/free path
(only faster). TRB runs are already serial per runner (enforced by the static
arena pool), so there is no correctness reason to gate it.
Mechanism (all host-side):
- HostApi exposes two slot accessors, get_retained_temp_buffer /
set_retained_temp_buffer. DeviceRunnerBase (onboard + sim) just remembers a
{addr, size} slot across runs and frees it once at finalize; it is not an
allocator.
- runtime_maker (a2a3 + a5) owns the whole mechanism in a file-local
RetainedTempBump: pack the run's non-child, non-empty tensors to a
1024-aligned required size, read the slot, grow (device_free old +
device_malloc new + write back) only when too small, then bump-slice each
tensor. 1024-byte alignment is what device_malloc already guarantees, so the
base and every slice stay aligned. Grow failure fails the run (no mid-run
malloc fallback); a backend that leaves the slot callbacks null falls back to
per-tensor device_malloc transparently.
- Ownership: TensorLease + TensorReleaseKind replace the implicit "every
recorded dev_ptr was malloc'd this run" assumption. Slice leases release as
no-ops; the Free kind covers the fallback path. child-memory and zero-byte
tensors are skipped (passed through unchanged).
Docs: RUNTIME_LOGIC.md §2.4 and task-flow.md describe the retained-buffer
mechanics. hbg is unaffected (host orchestration does not use the callbacks).
Verified: a2a3 + a5 sim + onboard build clean; Python worker UT 92 passed;
tensormap_and_ringbuffer prepared_callable + orch_so_cache a2a3sim ST pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2073441 to
61f49db
Compare
Summary
Cut the per-run
device_malloc/device_freeof ordinary non-child tensors on thetensormap_and_ringbuffer(TRB) bind path. TRB now stages them through a runner-scoped retained temporary buffer that grows to the high-water plan size and is reused across runs — steady-state (stable decode shapes) converges to zero temporary allocations.This is an internal allocation optimization, always on for TRB — there is no user-facing switch. It is always result-equivalent to the old malloc/free path (only faster), and TRB runs are already serial per runner (enforced by the static arena pool), so there is no correctness reason to gate it. The buffer is a single retained allocation per
DeviceRunnerBase;begin_temporary_buffer_run(plan)sizes it from the run's non-child tensors,acquireslices from it,validateends the run. Grow = free-old + alloc-new (no data preserved — per-run scratch); it never shrinks; on-exhaustion the run fails (no mid-run malloc fallback).Design notes
max_temporary_buffer_bytes, notemporary_buffer_mode, noconfigure_*entry across Python / pybind / C-ABI / ChipWorker.TensorLease+TensorReleaseKindreplace the implicit "every recorded dev_ptr was malloc'd this run" assumption: buffer slices release as no-ops (whole buffer reused at run end); theFreekind covers any backend that leaves the temp callbacks unwired and falls back todevice_malloc.See the runtime's
RUNTIME_LOGIC.md§2.4 anddocs/task-flow.mdfor mechanics.Testing
test_chip_worker,test_host_worker).tensormap_and_ringbuffer/prepared_callablea2a3sim — 7 passed (end-to-end register→run→validate with the buffer always on).test_temporary_variable_buffer,test_trb_runtime_temp_buffer) cover grow / reuse / shrink-noop / grow-failure / plan-sizing / child-memory pass-through / copy-back / lease-release — to be exercised by CI.Follow-up on the optimization direction discussed in #1186.