Conversation
_probe allocates its destination with torch.zeros, which enqueues the fill on the current stream, then enqueues the verification copy on a fresh probe stream. Nothing joins the two. When the current stream has a backlog the copy completes first on the independent probe stream and the fill lands on top of it, so the probe reads back zeros and load_batch_memcpy raises "cudaMemcpyBatchAsync probe copied wrong bytes" on a GPU that supports the API. OffloadMoeCache catches that and falls back to full-layer copies, so --moe-prefill-hit-d2d silently does nothing whenever the current stream is busy as the probe runs -- in practice during prefill warmup, which is exactly when the flag is first exercised. A cold process hides the bug: the first torch.zeros pays a cudaMalloc and the first torch.cuda.Stream() populates the per-device stream pool, and each of those synchronizes the device, draining the backlog before the copy is enqueued. That is why the probe passes when run standalone and fails inside a warmed-up server. Join the probe stream to the current stream before the copy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Reproduced, and it is biting a production deployment — so this is worth more than a tidy-up. Box: 2 x RTX 6000 Ada (sm_89), TP=2, Qwen3.8-Flash-Next NVFP4, offload MoE backend, torch 2.11.0+cu130, CUDA 13. Server runs with I ran
Eight queued matmuls is enough. Your explanation of why it looks fine standalone matches exactly: at backlog 0 and 1 it passes here too, because the first Why it matters beyond the probe. Two suggestions, neither blocking:
Taking the one-line fix onto our deploy branch now. 🤖 Generated with Claude Code |
…tself we already had Upstream FlashML-org#414 orders the batch-memcpy probe against the current stream, which is the same one-line fix MT made in a4b352e on 2026-08-29, twelve days earlier and never submitted. Our comment carries something theirs does not: the failure rate, 2 of 600 starts without the wait and 0 of 600 with it. So only the test is new. It exercises the ordering directly rather than through test_prefill_hit_d2d, which is where our three lines went. Cherry-picking the commit conflicts on the comment, so this takes the test file alone and leaves a4b352e's wording in place. Assisted-by: Claude Opus 5
…tself we already had Upstream FlashML-org#414 orders the batch-memcpy probe against the current stream, which is the same one-line fix MT made in a4b352e on 2026-08-29, twelve days earlier and never submitted. Our comment carries something theirs does not: the failure rate, 2 of 600 starts without the wait and 0 of 600 with it. So only the test is new. It exercises the ordering directly rather than through test_prefill_hit_d2d, which is where our three lines went. Cherry-picking the commit conflicts on the comment, so this takes the test file alone and leaves a4b352e's wording in place. Assisted-by: Claude Opus 5 (cherry picked from commit c22a2a2)
…nst the current stream
…nst the current stream
…nst the current stream
_probe allocates its destination with torch.zeros, which enqueues the fill on the current stream, then enqueues the verification copy on a fresh probe stream. Nothing joins the two. When the current stream has a backlog the copy completes first on the independent probe stream and the fill lands on top of it, so the probe reads back zeros and load_batch_memcpy raises "cudaMemcpyBatchAsync probe copied wrong bytes" on a GPU that supports the API.
OffloadMoeCache catches that and falls back to full-layer copies, so --moe-prefill-hit-d2d silently does nothing whenever the current stream is busy as the probe runs -- in practice during prefill warmup, which is exactly when the flag is first exercised.
A cold process hides the bug: the first torch.zeros pays a cudaMalloc and the first torch.cuda.Stream() populates the per-device stream pool, and each of those synchronizes the device, draining the backlog before the copy is enqueued. That is why the probe passes when run standalone and fails inside a warmed-up server.
Join the probe stream to the current stream before the copy.