Skip to content

Bolins/shm tensor arena - #51207

Open
BolinSNLHM wants to merge 15 commits into
vllm-project:mainfrom
CentML:bolins/shm-tensor-arena
Open

Bolins/shm tensor arena#51207
BolinSNLHM wants to merge 15 commits into
vllm-project:mainfrom
CentML:bolins/shm-tensor-arena

Conversation

@BolinSNLHM

@BolinSNLHM BolinSNLHM commented Aug 5, 2026

Copy link
Copy Markdown

Purpose

MessageQueue.enqueue (shm_broadcast.py) already routes CPU tensors out-of-band via
_reduce_tensor (protocol-5 PickleBuffer, #48442), which removed the dominant cost of
the old in-band path — copying tensor bytes into the pickle stream. Two costs remain for
a large multimodal pixel_values tensor on a TP=N worker:

  1. the out-of-band buffer is published once per node-local reader (N transport
    copies for TP=N), and
  2. each reader's H2D copies from a pageable ZMQ frame (pageable staging +
    first-touch faults).

This PR adds an opt-in slotted shared-memory tensor arena that layers on top of
_reduce_tensor: the writer does one memcpy into a free slot, every reader takes a
zero-copy view of the same slot (no per-reader transport copy), and the mapping is
cudaHostRegister-pinned so the H2D is a true DMA. Large contiguous CPU tensors are
diverted by _ArenaPickler.reducer_override; anything it declines (too small,
non-contiguous, or arena exhausted) falls through to _reduce_tensor unchanged.
Net for a ~200 MB image at TP=8: 1 memcpy + 8 pinned DMAs instead of 8 transport
copies + 8 pageable stagings
. The gain scales with TP degree and tensor size, and is
zero at TP=1 (no multiproc broadcast) — both now confirmed empirically below.

Design doc: docs/design/shm_tensor_arena.md.

Safety / scope: controlled by the --enable-shm-tensor-arena /
--no-enable-shm-tensor-arena CLI flag (ParallelConfig.enable_shm_tensor_arena,
default on — happy to flip to default-off if preferred); activates only when all queue
readers are node-local; the writer never blocks (no free/oversized slot → fall back
to _reduce_tensor, deadlock structurally impossible); slot reuse is gated on an
H2D-completion CUDA event, so the writer can't overwrite a slot whose async DMA is
still in flight — correct under --async-scheduling.

Test Plan

A/B against current main: the baseline arm is the unmodified
vllm/vllm-openai:nightly image (nightly-65b7662d3f…, includes #48442); the arena arm
is the same image plus this PR's four files. A third arm runs this PR's code with
--no-enable-shm-tensor-arena as a disable-control (must be behaviorally identical to
base; also bounds run-to-run noise).

Two setups, so the TP axis and the model-realism axis are both covered:

  1. TP-scaling sweep — Qwen2.5-VL-3B, TP ∈ {1, 2, 4} (ViT MLP dim caps this family
    at TP≤4), image sizes 512²–3072², 150 prompts @ 2 req/s.
  2. Production-scale VLM — Qwen3-VL-235B-A22B (ModelOpt NVFP4) on 8×B300,
    TP ∈ {4, 8}, image sizes 1024²/2048²/3072², 120 prompts @ 1 req/s.

Common method: vllm bench serve --dataset-name random-mm (openai-chat backend), one
image per request at a fixed size per cell, poisson arrivals at a non-saturated
rate, 20 warmups (excludes the one-time arena pinning), seed 42, 2 repeats per cell.
Built-in negative controls: TP=1 (arena structurally inactive) and 512² images (~3 MB
pixel_values, below the 8 MB divert threshold).

Repro commands

Server (one per arm × TP; arena arms = same image + this PR's files):

vllm serve $MODEL --tensor-parallel-size $TP --max-model-len 32768 \
  --mm-processor-cache-gb 0 [--enable-shm-tensor-arena | --no-enable-shm-tensor-arena]

Load (per image size HW, per repeat):

vllm bench serve --model $MODEL --backend openai-chat --endpoint /v1/chat/completions \
  --dataset-name random-mm --random-mm-bucket-config "{($HW, $HW, 1): 1.0}" \
  --random-mm-base-items-per-request 1 --random-mm-limit-mm-per-prompt '{"image": 1}' \
  --random-input-len 128 --random-output-len 64 --ignore-eos \
  --num-warmups 20 --num-prompts 150 --request-rate 2 --seed 42 \
  --percentile-metrics ttft,tpot,itl,e2el --metric-percentiles 50,90,99 --save-result

Still outstanding: port the standalone correctness harness (21 checks: byte-exact
round-trip incl. bf16, zero-copy sharing, slot lifecycle with per-reader release,
event-gated reuse, exhaustion/oversize/non-contiguous fallbacks) into
tests/distributed/test_shm_broadcast.py alongside the #48442 tests.

Test Result

Qwen3-VL-235B (NVFP4) on 8×B300 — E2E p99, base → arena (mean of 2 repeats):

image (pixel_values size) TP=4 TP=8
1024² (~23 MB) 1021 → 995 ms (−2.6%) 1025 → 999 ms (−2.5%)
2048² (~96 MB) 1584 → 1298 ms (−18.1%) 1807 → 1363 ms (−24.6%)
3072² (~213 MB) 3340 → 2771 ms (−17.0%) 4132 → 3083 ms (−25.4%)

TTFT p99 moves the same direction (TP=8: −21.5% at 2048², −11.9% at 3072²), and at these
payload sizes TTFT p50 improves too (TP=8/3072²: 1185 → 948 ms). Request throughput is
identical in every cell (rate-limited by design).

TP-scaling sweep (Qwen2.5-VL-3B — separate setup from the table above): TP=1 and
512² images are neutral (negative controls behave as designed — the arena never
activates); gains appear only at TP≥2 with ≥8 MB tensors and grow with TP and size. On
this small model the relative effect is larger than the 235B numbers above — up to −34%
E2E p99 at 3072²/TP=4 (3020 → 1992 ms) — because the same transport cost is a much
bigger fraction of a 3B's per-request time, and at 2 req/s its large-image cells carry
queueing that the stall removal also drains. The 235B table above is the more
conservative, production-representative measurement. The disable-control arm on this
setup bounds noise at roughly ±5% per cell.

Statistical honesty: with n=2 repeats, individual p99 cells are noisy (the 235B
control shows single-cell swings up to ~±17%). The claim rests on the pattern, not any
one cell: the arena is ahead in all 12 TTFT/E2E comparisons across both models,
monotonically in TP degree and tensor size — the shape the mechanism predicts
(per-reader transport + pageable staging replaced by one memcpy + pinned DMA), and the
E2E-tail bias matches head-of-line blocking on co-scheduled decodes.

Summary: neutral outside the large-image + TP≥2 regime; ~18–25% p99 reduction
inside it on a production-scale VLM.

Process note: the disable-control caught a bug in an earlier revision of this PR —
--no-enable-shm-tensor-arena was silently ignored (the gate read
get_current_vllm_config() outside its context and fell back to the default). Fixed by
threading the flag explicitly through the executor; the control was re-validated inert
(0 arena activations) before the numbers above.

Historical: original measurement vs the pre-#48442 in-band baseline

Same-seed interactive multimodal workload (uncapped images, TP=4 ×2 workers on one
8-GPU node, ~1.2k aligned requests): TTFT p50 93→89, p90 401→241, p99 1321→862, max
2139→1375 ms; requests >1.5 s: 9→0. These numbers predate #48442 and therefore overstate
the delta vs current main; kept only as provenance for the original problem analysis.


Essential Elements Checklist
  • Purpose of the PR
  • Test plan — executed (repro commands above); unit-test port to
    tests/distributed/ still outstanding
  • Test results — A/B vs current main on two models × TP 1–8, with disable-control
  • Documentation — docs/design/shm_tensor_arena.md

@claude claude 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.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the vLLM project.

💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in #pr-reviews, coordinate on features in #feat- channels, or join special interest groups in #sig- channels.

PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment /ci run whenever CI signals are needed.

Once the PR is approved or has the ready label, the PR author can also use /ci run or /ci retry. New commits do not start CI automatically.

If you have any questions, please reach out to us on Slack at https://slack.vllm.ai.

Agent Guidelines

IMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban.

🚀

@mergify

mergify Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Documentation preview: https://vllm--51207.org.readthedocs.build/en/51207/

@mergify mergify Bot added the documentation Improvements or additions to documentation label Aug 5, 2026
@wangshangsam

Copy link
Copy Markdown
Collaborator

opt-in via VLLM_SHM_TENSOR_ARENA (default on);

vLLM these days probably prefer a CLI flag instead.

@wangshangsam
wangshangsam requested a review from Isotr0py August 7, 2026 13:28
@Isotr0py Isotr0py self-assigned this Aug 7, 2026
Comment on lines +627 to +643
try:
if not torch.cuda.is_available():
return
import ctypes

buf = self.shared_memory.buf
assert buf is not None
ptr = ctypes.addressof(ctypes.c_char.from_buffer(buf))
ret = torch.cuda.cudart().cudaHostRegister(ptr, self.total_bytes, 0)
self._pinned = int(ret) == 0
logger.info(
"ShmTensorArena: cudaHostRegister(%d MB) -> %s",
self.total_bytes >> 20,
"pinned" if self._pinned else f"error {int(ret)}",
)
except Exception as e:
logger.info("ShmTensorArena: host-register skipped: %s", e)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's avoid using torch.cuda through current_platform and torch.acceleractor API instead?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done — switched to current_platform (is_cuda_alike() gate + current_platform.cudart() / .Event()), which resolves across CUDA/ROCm; the inherently-CUDA/ROCm cudaHostRegister stays behind the is_cuda_alike() guard, matching the existing pin_mmap_region pattern

Comment on lines +489 to +492
VLLM_SHM_TENSOR_ARENA = os.getenv("VLLM_SHM_TENSOR_ARENA", "1") != "0"
VLLM_SHM_TENSOR_ARENA_SLOTS = int(os.getenv("VLLM_SHM_TENSOR_ARENA_SLOTS", "8"))
VLLM_SHM_TENSOR_ARENA_SLOT_MB = int(os.getenv("VLLM_SHM_TENSOR_ARENA_SLOT_MB", "256"))
VLLM_SHM_TENSOR_ARENA_MIN_MB = int(os.getenv("VLLM_SHM_TENSOR_ARENA_MIN_MB", "8"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yea, we're avoiding increasing the num of env variables in vLLM. 😅

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done — the slot count/size and divert threshold are now internal module constants (_ARENA_SLOTS/_ARENA_SLOT_BYTES/_ARENA_MIN_BYTES), so no new env vars are added; the only user-facing knob is the single --enable-shm-tensor-arena / --no-enable-shm-tensor-arena CLI flag (ParallelConfig.enable_shm_tensor_arena, default on)

@Isotr0py

Isotr0py commented Aug 7, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: effa08b4f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +540 to +542
self.shared_memory = shared_memory.SharedMemory(
create=True, size=self.total_bytes
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Check shared-memory capacity before creating the arena

When the default-on arena is created, it reserves 8 × 256 MiB without calling the existing check_shm_free_space guard. On containers whose /dev/shm is smaller than 2 GiB, SharedMemory/ftruncate can initially succeed, but copying a large tensor into pages beyond the tmpfs capacity can terminate the process with SIGBUS; the ring buffer avoids this failure by checking capacity before allocation. Check the arena's total_bytes before creating it, including the space already reserved by the ring buffer.

Useful? React with 👍 / 👎.

Comment on lines +652 to +655
slot_mv = self._slot(idx, nbytes)
t8 = torch.frombuffer(slot_mv, dtype=torch.uint8, count=nbytes)
t = t8.view(dtype).view(shape)
self._pending_release.append(idx)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep slots reserved while returned tensors remain live

For any caller that retains a large CPU tensor after requesting the next message—for example, an RPC method that caches its input—the next dequeue() moves this slot toward release regardless of whether the returned tensor is still referenced. Once every reader does so, the writer can reuse the slot and silently mutate the previously returned tensor; the CUDA event only protects an assumed H2D copy, not subsequent CPU access or object lifetime. The prior out-of-band path kept its frame alive through the tensor's storage, so slot release likewise needs to be tied to the returned view's lifetime or an explicit consumption acknowledgement.

Useful? React with 👍 / 👎.

Comment on lines +745 to +750
isinstance(obj, torch.Tensor)
and obj.device.type == "cpu"
and obj.layout == torch.strided
and obj.is_contiguous()
and obj.numel() * obj.element_size()
>= VLLM_SHM_TENSOR_ARENA_MIN_MB * 1024 * 1024

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve autograd metadata on arena tensors

When a contiguous CPU tensor at least MIN_MB has requires_grad=True, this override now selects the arena even though _reduce_tensor deliberately excludes such tensors and delegates to PyTorch's normal reducer. write_tensor() detaches the source and _rebuild_arena_tensor() constructs a fresh tensor with requires_grad=False, so the round trip silently drops its autograd state. Add the same not obj.requires_grad restriction here or explicitly reconstruct the metadata.

Useful? React with 👍 / 👎.

Comment on lines +911 to +913
_TENSOR_ARENAS[self.tensor_arena.shared_memory.name] = (
self.tensor_arena
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clean up registered reader arenas

In a long-lived process that creates and destroys multiple reader queues, this module-level dictionary holds every attached arena strongly forever. MessageQueue.shutdown() neither removes the entry nor calls cudaHostUnregister, so each queue can retain a 2 GiB mapping and its CUDA host registration until process exit, eventually exhausting virtual address or pinned-memory limits during executor recreation. Add an explicit arena cleanup path that unregisters pinned memory, removes the matching registry entry, and closes the mapping.

Useful? React with 👍 / 👎.

@njhill

njhill commented Aug 8, 2026

Copy link
Copy Markdown
Member

Thanks @BolinSNLHM! I had thought about doing something like this before.

But the numbers don't look super convincing to me, not sure it would justify the extra complexity / configuratin burden. It would be good to have some more comprehensive benchmarks testing realistic workloads with large images and varying TP sizes, and importantly comparing against current main which already has the oob tensor pickling optimization.

@wangshangsam

wangshangsam commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

@njhill

But the numbers don't look super convincing to me,
to have some more comprehensive benchmarks testing realistic workloads with large images and varying TP sizes

It does have a big E2E impact (like ~1.5x) for maximizing the QPS under a ultra-low P99 latency bound scenario in the MLPerf Inference VLM (Qwen3-VL) benchmark with a PD disagg topology. Unfortunately, MLPerf v6.1 results are still under embargo so we can't post it here.

not sure it would justify the extra complexity / configuratin burden

As with all advanced perf optimization techniques, users are free to choose to not use them.

and importantly comparing against current main which already has the oob tensor pickling optimization

This is a fair request but which "oob tensor pickling optimization" exactly are you refer to? (So that @BolinSNLHM would choose the intended baseline correctly)

@njhill

njhill commented Aug 10, 2026

Copy link
Copy Markdown
Member

Thanks @wangshangsam

and importantly comparing against current main which already has the oob tensor pickling optimization

This is a fair request but which "oob tensor pickling optimization" exactly are you refer to? (So that @BolinSNLHM would choose the intended baseline correctly)

Could just use the latest main branch? The optimization I'm referring to in particular is #48442, which was merged 2 weeks ago.

…Queue

Large multimodal pixel_values tensors (100-200MB) were pickle-serialized
into the broadcast payload on the engine (THPStorage_writeFileRaw) and
deserialized on every local TP reader (THPStorage_readFileRaw), blocking
the EngineCore step loop ~1s per large image with all GPUs idle.

Add ShmTensorArena: a slotted shared-memory region (per-slot reader flags,
same protocol as ShmRingBuffer). A Pickler.reducer_override diverts large
contiguous CPU tensors into a free slot (single memcpy) and pickles only a
(slot, nbytes, dtype, shape) stub; readers rebuild the tensor as a
zero-copy torch.frombuffer view of the mapped slot. Slots are released
lazily at the reader's next dequeue (worker loop is sequential, so the
previous step's HtoD has completed). The writer never blocks: no free
slot or oversize tensor falls back to the default in-band pickling.

Env knobs: VLLM_SHM_TENSOR_ARENA (default on), _SLOTS (8), _SLOT_MB (256),
_MIN_MB (8). Local readers only; disabled when remote readers exist.

Unit test: 199MB bf16 roundtrip to 2 forked readers = 66.7ms enqueue
(vs ~1275ms pickled), checksums exact, slot reuse + fallback verified.

Signed-off-by: Bolin Sun <bolins@nvidia.com>
The zero-copy tensor views the tmpfs mapping; without pinning, the HtoD
pays first-touch page faults + pageable staging (~600-800ms observed for
a 192MB image). Lazy one-time cudaHostRegister at first get_tensor makes
every later HtoD a true DMA. Falls back gracefully when the process has
no CUDA context.

Signed-off-by: Bolin Sun <bolins@nvidia.com>
Documents the multimodal engine->worker transport bottleneck (in-band
pickle of large pixel_values tensors in MessageQueue.enqueue, per-rank
deserialize, engine-loop head-of-line blocking) and the ShmTensorArena
zero-copy design that removes it, including the pinning rationale,
configuration knobs, validation results, and known limitations.

Signed-off-by: Bolin Sun <bolins@nvidia.com>
Slots were released at the reader's next dequeue on the premise that the consuming HtoD had completed by then. That holds only for a pageable source (cudaMemcpyAsync stages synchronously before returning). But readers cudaHostRegister-pin the arena, making the HtoD a true async DMA, and --async-scheduling removes the sampler's covering device sync -- so the DMA can still be reading a slot when the writer reclaims and overwrites it. Masked in practice by the 8-slot round-robin depth, but a latent data race on the deployed path.

flush_releases now records a CUDA event on the compute stream (ordered after the previous step's HtoD) and frees a slot only once event.query() reports the DMA complete; a slot not yet done waits one more dequeue. Unpinned / no-CUDA readers release immediately as before (the pageable copy already staged synchronously). The writer never blocks: undrained slots stay busy and write_tensor falls back to pickle, preserving the deadlock-free invariant.

Signed-off-by: Bolin Sun <bolins@nvidia.com>
… channel

Upstream `_reduce_tensor` already routes CPU tensors out-of-band, removing the in-band serialize copy the arena was originally motivated against. Reposition the doc accordingly: the arena's remaining value is collapsing the N per-reader transport copies to one (scales with TP degree) plus the pinned-vs-pageable reader H2D. Label the existing benchmarks as measured against the pre-oob in-band baseline, and flag the arena-vs-oob A/B on current main as the outstanding validation item.

Signed-off-by: Bolin Sun <bolins@nvidia.com>
…hm-tensor-arena) instead of an env var (review: prefer a CLI flag)

Signed-off-by: Bolin Sun <bolins@nvidia.com>
…orch.cuda for the arena's pinning and release-gating (review: avoid torch.cuda)

Signed-off-by: Bolin Sun <bolins@nvidia.com>
…nv vars (review: avoid adding env variables)

Signed-off-by: Bolin Sun <bolins@nvidia.com>
…ants

Signed-off-by: Bolin Sun <bolins@nvidia.com>
…(the CLI flag was silently ignored)

get_current_vllm_config() raises outside a set_current_vllm_config() context, so the previous ambient lookup always fell back to the default (enabled) and --no-enable-shm-tensor-arena had no effect. Benchmarking caught this: the disabled control arm still pinned the arena. Pass the value from ParallelConfig at the executor instead.

Signed-off-by: Bolin Sun <bolins@nvidia.com>
@BolinSNLHM
BolinSNLHM force-pushed the bolins/shm-tensor-arena branch from 7ec4f02 to 186b409 Compare August 12, 2026 16:31
@BolinSNLHM
BolinSNLHM requested a review from njhill as a code owner August 12, 2026 16:31
Default-on would change behavior for MessageQueue constructions that don't thread the config flag (e.g. the ray executor) and alters the tensor path exercised by the existing test_tensor_broadcast. Off by default keeps stock behavior everywhere unless --enable-shm-tensor-arena is passed, and addresses the configuration-burden review concern.

Signed-off-by: Bolin Sun <bolins@nvidia.com>
…or tests

Covers: byte-exact zero-copy round-trips (readers alias one mapping; bf16/fp8 via the uint8 view path), slot lifecycle (no reuse until every reader releases; exhaustion, oversize and non-contiguous inputs fall back), _ArenaPickler composition with _reduce_tensor (large diverted to a slot, everything declined takes the out-of-band path unchanged), CUDA-event-gated release on the pinned path (GPU-only), and an end-to-end MessageQueue broadcast with a forked reader verifying the received tensor aliases an arena slot.
Signed-off-by: Bolin Sun <bolins@nvidia.com>
@BolinSNLHM

Copy link
Copy Markdown
Author

@njhill The benchmarks you asked for are in -- baseline is current main (pinned nightly-65b7662d3f…, which includes #48442's oob tensor pickling), measured with vllm bench serve --dataset-name random-mm at a non-saturated rate, 2 repeats per cell, plus a --no-enable-shm-tensor-arena control arm (verified inert, 0 arena activations). Full method, reproduce commands and tabels are in the updated PR description; the branch is rebased onto the latest main

Headline: on Qwen3-VL-235B-A22B NVFP4, 8×B300 — E2E p99 vs
main:

image TP=4 TP=8
1024² (~23 MB pixel_values) −2.6% −2.5%
2048² (~96 MB) −18.1% −24.6%
3072² (~213 MB) −17.0% −25.4%

And TTFT p99 moves the same way (-21.5% at TP=8/2048² image size), and TP=1 with sub-8MB images are confirmed neutral

So the honest summary: neutral outside the large-image + TP>=2 regime, and 17-25% p99 latency reduction inside it - a targeted optimization for high-resolution multimodal serving under TP, not a universally applicable optimization.

On the complexity/config concern: the latest version makes the arena default off and strictly opt-in: no env vars, a single --enable-shm-tensor-arena flag, and with the flag off, the code path is byte-identical to main. I have also added unit tests in tests/distributed/test_shm_broadcast.py: zero-copy round-trips, the slot-lifecycle race protection(no reuse until every reader releases), all fallback paths, the CUDA-event-gated release on the pinned path, and an end-to-end MessageQueue broadcast verifying the received tensor aliases an arena slot.

buf = self.shared_memory.buf
assert buf is not None
ptr = ctypes.addressof(ctypes.c_char.from_buffer(buf))
ret = current_platform.cudart().cudaHostRegister(ptr, self.total_bytes, 0)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maybe also need to call cudaHostUnregister to clear up registered memory.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done -- the arena now pairs the registration with a cudaHostUnregister in __del__, before the mapping is closed. Added a unit test asserting the register/unregister pairing.

Comment on lines +912 to +914
_TENSOR_ARENAS[self.tensor_arena.shared_memory.name] = (
self.tensor_arena
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If one worker only has one tensor_arena, we do not need to maintain a list like _TENSOR_ARENAS.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good point; now I replaced the dict with a single module-level _TENSOR_ARENA

BolinSNLHM and others added 3 commits August 20, 2026 15:28
Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Bolin Sun <bolins@nvidia.com>
Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Bolin Sun <bolins@nvidia.com>
Co-authored-by: Claude <noreply@anthropic.com>
Signed-off-by: Bolin Sun <bolins@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation nvidia

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

5 participants