Skip to content

Remove excessive CuteDslMoEWrapper memory allocation - #3404

Merged
samuellees merged 1 commit into
flashinfer-ai:mainfrom
nvjullin:cutedsl-drop-buffers
Jun 10, 2026
Merged

samuellees merged 1 commit into
flashinfer-ai:mainfrom
nvjullin:cutedsl-drop-buffers

Conversation

@nvjullin

@nvjullin nvjullin commented May 26, 2026

Copy link
Copy Markdown
Contributor

📌 Description

Resolves #3308.
Previously, max_num_tokens were only checked in cuda graph path, but now deprecated and unused.
Dropped tests that test for pre-allocated buffers.

🔍 Related Issues

🚀 Pull Request Checklist

Thank you for contributing to FlashInfer! Before we review your pull request, please make sure the following items are complete.

✅ Pre-commit Checks

  • I have installed pre-commit by running pip install pre-commit (or used your preferred method).
  • I have installed the hooks with pre-commit install.
  • I have run the hooks manually with pre-commit run --all-files and fixed any reported issues.

If you are unsure about how to set up pre-commit, see the pre-commit documentation.

🧪 Tests

  • Tests have been added or updated as needed.
  • All tests are passing (unittest, etc.).

Reviewer Notes

Summary by CodeRabbit

  • API Changes

    • max_num_tokens is now optional/deprecated (ignored at runtime); existing calls remain compatible.
  • Performance Improvements

    • Persistent CUDA stream/event handling improves CUDA-graph compatibility and enables better async-memset overlap, reducing memory overhead.
  • Tests

    • Tests updated to validate routing/buffer write-completeness via the core execution path using poisoned-buffer checks.
  • Documentation

    • Docstrings updated to reflect the new persistent CUDA resource model and deprecated max_num_tokens.

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 77004de2-37af-4925-8830-df1333825156

📥 Commits

Reviewing files that changed from the base of the PR and between 3a40dce24a505fe1a002782386b663faa1605abd and cf4ac21.

📒 Files selected for processing (3)
  • flashinfer/fused_moe/cute_dsl/fused_moe.py
  • flashinfer/fused_moe/cute_dsl/tuner.py
  • tests/moe/test_cute_dsl_fused_moe.py
✅ Files skipped from review due to trivial changes (1)
  • flashinfer/fused_moe/cute_dsl/tuner.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/moe/test_cute_dsl_fused_moe.py
  • flashinfer/fused_moe/cute_dsl/fused_moe.py

📝 Walkthrough

Walkthrough

This PR replaces per-layer preallocated MOE/GEMM buffers with persistent CUDA Stream/Event resources for CUDA-graph compatibility, deprecates max_num_tokens, always allocates fresh moe_output, invokes _moe_core_impl without wrapper-managed buffers, and updates tests to inject routing buffers directly.

Changes

CUDA-graph buffer preallocation removal

Layer / File(s) Summary
API contract: max_num_tokens deprecation
flashinfer/fused_moe/cute_dsl/fused_moe.py
Constructor signature changes max_num_tokens from int = 4096 to Optional[int] = None; module and class docstrings mark it deprecated/ignored and describe persistent CUDA stream/event resources.
Constructor: persistent CUDA stream/event model
flashinfer/fused_moe/cute_dsl/fused_moe.py
Imports adjusted; constructor creates persistent torch.cuda.Stream and torch.cuda.Event when use_cuda_graph=True and removes prior per-layer buffer preallocation/state.
Forward path and run(): remove preallocated buffer gating
flashinfer/fused_moe/cute_dsl/fused_moe.py
Removed conditional "use preallocated buffers" gate in _forward_with_tactic; _moe_core_impl is invoked without wrapper preallocated moe_sort_buffers/gemm1_out/gemm1_out_scale; run() always creates a fresh moe_output and drops output-slice reuse and max_num_tokens checks.
Tests: moe_sort poisoning and prealloc removals
tests/moe/test_cute_dsl_fused_moe.py
Poisoning invariant test now allocates moe_sort_buffers via allocate_moe_sort_buffers, fills them with a sentinel, and calls _moe_core_impl with tile_size and output_dtype; old prealloc-focused tests removed.
Supporting comment updates
flashinfer/fused_moe/cute_dsl/tuner.py
Shortened VALID_TILE_SIZES comment to remove stale reference to wrapper buffer-sizing behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

cute-dsl

Suggested reviewers

  • yzh119
  • samuellees
  • IwakuraRein
  • jiahanc
  • nv-yunzheq

Poem

🐰 Per-layer buffers weighed a ton,
Streams and events now get it done.
Poisoned tensors checked with care,
Fresh outputs rise from open air.
Hop — CUDA graphs breathe lighter!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: removing excessive memory allocation from CuteDslMoEWrapper through eliminating per-layer buffer preallocation.
Description check ✅ Passed The PR description addresses the template sections (Description links to issue #3308, marks pre-commit checks complete, reports tests updated/passing), though the Related Issues section lacks explicit issue link formatting.
Linked Issues check ✅ Passed The PR successfully addresses issue #3308 objectives: it removes per-layer buffer preallocation in CuteDslMoEWrapper.init when use_cuda_graph=True, deprecates max_num_tokens parameter, updates tests to use internal _moe_core_impl path, and eliminates preallocated-buffer integration tests.
Out of Scope Changes check ✅ Passed All changes are in-scope: modifications to CuteDslMoEWrapper buffer allocation logic, tuner.py comment cleanup, and test updates directly align with removing excessive per-layer buffer preallocation requirements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the CuteDslMoEWrapper class to remove pre-allocated buffers, shifting instead to holding persistent CUDA stream and event resources for async-memset overlap and CUDA graph compatibility. The max_num_tokens parameter is deprecated and ignored. The associated tests are updated to reflect these changes. The review feedback highlights a high-severity concurrency risk where multi-threaded environments could suffer from race conditions on shared global CUDA resources when use_cuda_graph=False. Additionally, a high-severity concern is raised regarding CUDA graph memory safety due to dynamic allocation of moe_output inside run(), suggesting allowing user-managed output buffers. Finally, a deprecation warning is recommended for the deprecated max_num_tokens parameter.

Comment on lines 439 to +442
if use_cuda_graph:
self._allocate_buffers()

def _allocate_buffers(self) -> None:
"""Pre-allocate all buffers for CUDA graph compatibility.

Buffers are sized to fit *any* ``tile_size in VALID_TILE_SIZES``,
not just ``self.tile_size``. Two distinct buffer-shape concerns:

- ``max_num_permuted_tokens`` is monotonically *increasing* in
``tile_size`` (the ``(tile - 1) * num_local_experts`` padding
term grows faster than ``max_num_tiles`` shrinks), so
permuted-token-indexed buffers (``_gemm1_output``,
``_gemm1_output_scale``,
``out_permuted_idx_to_expanded_idx``) must be sized using
``max(VALID_TILE_SIZES)``.
- ``max_num_tiles`` is monotonically *decreasing* in
``tile_size``, so the tile-count-indexed moe_sort buffers
(``out_tile_idx_to_expert_idx``,
``out_tile_idx_to_mn_limit``) must be sized using
``min(VALID_TILE_SIZES)``.

Sizing this way means the ``use_prealloc`` gate at
``_forward_with_tactic`` doesn't need a ``tile_size ==
self.tile_size`` check at runtime: whichever tactic the
autotuner picked, the prealloc fits. This preserves the
wrapper's CUDA-graph contract (``run()`` is graph-safe with
``use_cuda_graph=True``) regardless of which ``tile_size`` the
autotuner ends up choosing.
"""
smallest_tile = min(VALID_TILE_SIZES)
largest_tile = max(VALID_TILE_SIZES)
max_permuted_across_tiles = get_max_num_permuted_tokens(
self.max_num_tokens, self.top_k, self.num_local_experts, largest_tile
)

# moe_sort buffers — allocate using smallest_tile so the
# tile-count-indexed buffers (out_tile_idx_to_expert_idx,
# out_tile_idx_to_mn_limit) are large enough for any tile_size,
# then override out_permuted_idx_to_expanded_idx (which scales
# with tile_size in the opposite direction) to fit the largest
# tile_size's max_num_permuted_tokens.
self._moe_sort_buffers = allocate_moe_sort_buffers(
num_tokens=self.max_num_tokens,
num_experts=self.num_experts,
top_k=self.top_k,
num_local_experts=self.num_local_experts,
tile_tokens_dim=smallest_tile,
device=self.device,
)
self._moe_sort_buffers["out_permuted_idx_to_expanded_idx"] = torch.empty(
(max_permuted_across_tiles,), dtype=torch.int32, device=self.device
)

# GEMM1 output (FP4 quantized)
self._gemm1_output = torch.empty(
(max_permuted_across_tiles, self.intermediate_size // 2),
dtype=torch.uint8,
device=self.device,
)

# GEMM1 output scale
scale_size = max_permuted_across_tiles * (
self.intermediate_size // self.sf_vec_size
)
self._gemm1_output_scale = torch.empty(
(scale_size,), dtype=torch.uint8, device=self.device
)

# Final output
self._moe_output = torch.empty(
(self.max_num_tokens, self.hidden_size),
dtype=self.output_dtype,
device=self.device,
)

# CUDA resources
self._aux_stream = torch.cuda.Stream(device=self.device)
self._main_event = torch.cuda.Event()
self._memset_event = torch.cuda.Event()
self._aux_stream = torch.cuda.Stream(device=self.device)
self._main_event = torch.cuda.Event()
self._memset_event = torch.cuda.Event()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Concurrency Risk / Race Condition in Multi-threaded Environments

When use_cuda_graph=False, self._aux_stream, self._main_event, and self._memset_event are left as None. During execution, _moe_core_impl falls back to the module-level _get_cuda_graph_resources(), which returns a single globally shared set of stream and event resources.

If multiple threads concurrently execute CuteDslMoEWrapper instances with use_cuda_graph=False, they will share the same CUDA stream and events. This leads to severe race conditions (e.g., concurrent record() and wait() calls on the same events), resulting in premature synchronization, undefined behavior, or silent data corruption.

To ensure thread safety, we should always initialize instance-specific stream and event resources in __init__ regardless of use_cuda_graph.

        self._aux_stream = torch.cuda.Stream(device=self.device)
        self._main_event = torch.cuda.Event()
        self._memset_event = torch.cuda.Event()

Comment on lines +546 to +550
moe_output = torch.empty(
(num_tokens, self.hidden_size),
dtype=self.output_dtype,
device=x.device,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

CUDA Graph Memory Safety & API Inconsistency

With the removal of pre-allocated buffers, moe_output is now always allocated dynamically inside run() via torch.empty(). When capturing a CUDA graph, this dynamic allocation is captured. If the user does not manually keep the returned tensor alive across graph replays, PyTorch's caching allocator may reuse its memory for other eager-mode tensors, leading to silent memory corruption during replay.

To allow safe user-managed output buffers (and to align with the functional API cute_dsl_fused_moe_nvfp4 which already accepts moe_output), we should add moe_output: Optional[torch.Tensor] = None to the signature of CuteDslMoEWrapper.run() and only allocate it if it is not provided.

Suggested change
moe_output = torch.empty(
(num_tokens, self.hidden_size),
dtype=self.output_dtype,
device=x.device,
)
if moe_output is None:
moe_output = torch.empty(
(num_tokens, self.hidden_size),
dtype=self.output_dtype,
device=x.device,
)

@@ -392,7 +396,6 @@ def __init__(
self.hidden_size = hidden_size
self.intermediate_size = intermediate_size
self.use_cuda_graph = use_cuda_graph

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Missing Deprecation Warning for max_num_tokens

Since max_num_tokens is now deprecated and ignored, we should raise a DeprecationWarning if the user passes a non-None value. This ensures users are aware of the deprecation and can clean up their codebases accordingly.

Suggested change
self.use_cuda_graph = use_cuda_graph
self.use_cuda_graph = use_cuda_graph
if max_num_tokens is not None:
import warnings
warnings.warn(
"max_num_tokens is deprecated and ignored.",
DeprecationWarning,
stacklevel=2,
)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
flashinfer/fused_moe/cute_dsl/fused_moe.py (1)

89-98: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Key _cuda_graph_resources by CUDA device (avoid global stream/event reuse across GPUs).

_cuda_graph_resources memoizes one stream/event trio process-wide, and _moe_core_impl() falls back to it whenever aux_stream, main_event, or memset_event is missing. The functional API never supplies main_event/memset_event, and the wrapper only supplies these when use_cuda_graph=True; otherwise it also hits the fallback. Because torch.cuda.Event() / torch.cuda.Stream() are created without an explicit device, they bind to the current CUDA device at first call and can be reused when x is on a different GPU. Scope the cache by device (e.g., x.device) and create events/streams on that device explicitly.

🤖 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 `@flashinfer/fused_moe/cute_dsl/fused_moe.py` around lines 89 - 98, The
_cuda_graph_resources cache is process-wide and can return events/streams
created on a different GPU; change _get_cuda_graph_resources to key the cache by
CUDA device and create events/streams explicitly on that device (use x.device or
torch.cuda.current_device() when called), e.g., store per-device entries like
_cuda_graph_resources[device] = {"main_event": torch.cuda.Event(device=device),
"memset_event": torch.cuda.Event(device=device), "aux_stream":
torch.cuda.Stream(device=device)}; update callers (e.g., _moe_core_impl and any
functional wrappers that rely on aux_stream, main_event, memset_event) to pass
the tensor/device to _get_cuda_graph_resources so they always receive
device-local events/streams and avoid cross-GPU reuse.
🧹 Nitpick comments (1)
flashinfer/fused_moe/cute_dsl/fused_moe.py (1)

365-385: ⚡ Quick win

Warn when max_num_tokens is still provided.

The docs now say this parameter is deprecated and ignored, but callers get no signal that the old sizing contract disappeared. Emitting a DeprecationWarning here makes the API change discoverable before downstream code keeps passing a dead config knob.

♻️ Suggested change
+import warnings
+
 from typing import Any, Dict, Optional, Tuple
@@
         """Initialize the MoE wrapper.
@@
         self.output_dtype = output_dtype
         self.device = device
         self.enable_pdl = enable_pdl
+        if max_num_tokens is not None:
+            warnings.warn(
+                "`max_num_tokens` is deprecated and ignored by "
+                "`CuteDslMoEWrapper`.",
+                DeprecationWarning,
+                stacklevel=2,
+            )
🤖 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 `@flashinfer/fused_moe/cute_dsl/fused_moe.py` around lines 365 - 385, In the
MoE wrapper initializer where the parameter max_num_tokens is accepted (the
constructor in fused_moe.py that currently documents "max_num_tokens" as
deprecated), add a runtime deprecation warning: when max_num_tokens is not None,
call warnings.warn with a clear message that max_num_tokens is deprecated and
ignored, use category=DeprecationWarning and set an appropriate stacklevel
(e.g., stacklevel=2) so callers see the source; import the warnings module if
not already present.
🤖 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.

Outside diff comments:
In `@flashinfer/fused_moe/cute_dsl/fused_moe.py`:
- Around line 89-98: The _cuda_graph_resources cache is process-wide and can
return events/streams created on a different GPU; change
_get_cuda_graph_resources to key the cache by CUDA device and create
events/streams explicitly on that device (use x.device or
torch.cuda.current_device() when called), e.g., store per-device entries like
_cuda_graph_resources[device] = {"main_event": torch.cuda.Event(device=device),
"memset_event": torch.cuda.Event(device=device), "aux_stream":
torch.cuda.Stream(device=device)}; update callers (e.g., _moe_core_impl and any
functional wrappers that rely on aux_stream, main_event, memset_event) to pass
the tensor/device to _get_cuda_graph_resources so they always receive
device-local events/streams and avoid cross-GPU reuse.

---

Nitpick comments:
In `@flashinfer/fused_moe/cute_dsl/fused_moe.py`:
- Around line 365-385: In the MoE wrapper initializer where the parameter
max_num_tokens is accepted (the constructor in fused_moe.py that currently
documents "max_num_tokens" as deprecated), add a runtime deprecation warning:
when max_num_tokens is not None, call warnings.warn with a clear message that
max_num_tokens is deprecated and ignored, use category=DeprecationWarning and
set an appropriate stacklevel (e.g., stacklevel=2) so callers see the source;
import the warnings module if not already present.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4cad15ad-f5a8-447c-b1fd-596b20c33147

📥 Commits

Reviewing files that changed from the base of the PR and between 56d537a and b3f413dc51ead4d22de3a08a6e57fc36017deb0a.

📒 Files selected for processing (3)
  • flashinfer/fused_moe/cute_dsl/fused_moe.py
  • flashinfer/fused_moe/cute_dsl/tuner.py
  • tests/moe/test_cute_dsl_fused_moe.py

@aleozlx aleozlx added the run-ci label May 26, 2026
@aleozlx

aleozlx commented May 26, 2026

Copy link
Copy Markdown
Member

/bot run

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !717 has been created, and the CI pipeline #52700725 is currently running. I'll report back once the pipeline job completes.

@aleozlx aleozlx left a comment

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.

looks good

@aleozlx aleozlx self-assigned this May 26, 2026
@nvpohanh

Copy link
Copy Markdown
Contributor

/bot run

@nvpohanh

Copy link
Copy Markdown
Contributor

@nv-yunzheq could you also review this?

and cc @leejnau for vis

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !717 has been created, and the CI pipeline #52742657 is currently running. I'll report back once the pipeline job completes.

@nvpohanh

nvpohanh commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

@nvjullin could you rebase so that I can trigger another pipeline? thanks!

@nvjullin
nvjullin force-pushed the cutedsl-drop-buffers branch from b3f413d to 3a40dce Compare June 3, 2026 07:10
@nvjullin

nvjullin commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
flashinfer/fused_moe/cute_dsl/fused_moe.py (1)

365-365: 💤 Low value

Consider emitting a deprecation warning when max_num_tokens is provided.

Users passing a non-None max_num_tokens value may not notice it's being ignored unless they read the updated docstring. A warnings.warn(..., DeprecationWarning) would surface this more explicitly.

This is optional since the docstring already documents the deprecation clearly.

Also applies to: 381-385

🤖 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 `@flashinfer/fused_moe/cute_dsl/fused_moe.py` at line 365, If callers pass a
non-None max_num_tokens (which is deprecated) add an explicit warnings.warn call
to surface this; in the functions/methods where max_num_tokens appears (e.g.,
the signature containing max_num_tokens: Optional[int] = None around the
fused_moe.py region and the other occurrences at the 381-385 block), import the
warnings module if needed and at the start of each function check "if
max_num_tokens is not None:" then call warnings.warn("max_num_tokens is
deprecated and will be ignored; please remove it.", DeprecationWarning,
stacklevel=2) so users see the deprecation when they pass a value.
🤖 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.

Nitpick comments:
In `@flashinfer/fused_moe/cute_dsl/fused_moe.py`:
- Line 365: If callers pass a non-None max_num_tokens (which is deprecated) add
an explicit warnings.warn call to surface this; in the functions/methods where
max_num_tokens appears (e.g., the signature containing max_num_tokens:
Optional[int] = None around the fused_moe.py region and the other occurrences at
the 381-385 block), import the warnings module if needed and at the start of
each function check "if max_num_tokens is not None:" then call
warnings.warn("max_num_tokens is deprecated and will be ignored; please remove
it.", DeprecationWarning, stacklevel=2) so users see the deprecation when they
pass a value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eb774c81-b335-496e-b565-e2a9a432e573

📥 Commits

Reviewing files that changed from the base of the PR and between b3f413dc51ead4d22de3a08a6e57fc36017deb0a and 3a40dce24a505fe1a002782386b663faa1605abd.

📒 Files selected for processing (3)
  • flashinfer/fused_moe/cute_dsl/fused_moe.py
  • flashinfer/fused_moe/cute_dsl/tuner.py
  • tests/moe/test_cute_dsl_fused_moe.py
💤 Files with no reviewable changes (1)
  • tests/moe/test_cute_dsl_fused_moe.py
✅ Files skipped from review due to trivial changes (1)
  • flashinfer/fused_moe/cute_dsl/tuner.py

@nvpohanh

nvpohanh commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

/bot run

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !717 has been updated with latest changes, and the CI pipeline #53509427 is currently running. I'll report back once the pipeline job completes.

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

[FAILED] Pipeline #53509427: 12/20 passed

@nvjullin

nvjullin commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author
FAILED: tests/utils/test_sampling.py
FAILED: tests/gemm/test_groupwise_scaled_gemm_fp8.py

First failure is known issue #3470.
Second seems completely unrelated.

@nvpohanh

nvpohanh commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

@nvjullin could you fix the conflicts?

@nvjullin
nvjullin force-pushed the cutedsl-drop-buffers branch from 3a40dce to cf4ac21 Compare June 8, 2026 08:40
@nvjullin

nvjullin commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Done, it was a docstring style rewrite causing conflicts.

@samuellees

Copy link
Copy Markdown
Collaborator

/bot run tests/moe

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !717 has been updated with latest changes, and the CI pipeline #54060962 is currently running. I'll report back once the pipeline job completes.

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

[FAILED] Pipeline #54060962: 11/20 passed

@samuellees samuellees left a comment

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.

LGTM, thanks for the contribution!

@samuellees
samuellees merged commit 2aa1d49 into flashinfer-ai:main Jun 10, 2026
32 of 35 checks passed
vitamin-chaos added a commit to vitamin-chaos/flashinfer that referenced this pull request Aug 11, 2026
Follows the NVFP4 wrapper (flashinfer-ai#3404): CUDA graph capture records allocations
from its private pool, so pre-sizing workspace for a maximum batch never
helped capture and only cost memory. Drop the output, routing, intermediate
and scale buffers and keep just the persistent stream and events, which do
have to exist before capture.

max_num_tokens is now accepted but ignored, matching CuteDslMoEWrapper. This
also removes the per-batch-size buffer caches, which grew without bound when
max_num_tokens was unset, and makes run() return a caller-owned tensor
instead of a view of wrapper storage that the next call overwrites.

AI-assisted with Claude Code.

Signed-off-by: Tiekai Bi <tiekaib@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Excessive per-layer buffer allocation in CuteDslMoEWrapper when use_cuda_graph=True

5 participants