perf(mamba): use Triton conv1d for non-contiguous input to avoid .contiguous() copy (#20469)

This commit is contained in:
Jia Guo
2026-03-19 19:38:46 -07:00
committed by GitHub
parent db995fba47
commit 87549f8f0b
2 changed files with 21 additions and 16 deletions
@@ -9,20 +9,23 @@ from typing import Optional
import torch import torch
from .causal_conv1d_triton import PAD_SLOT_ID from .causal_conv1d_triton import PAD_SLOT_ID
from .causal_conv1d_triton import causal_conv1d_fn as _causal_conv1d_fn_triton
from .causal_conv1d_triton import causal_conv1d_update as _causal_conv1d_update_triton
try: try:
from sgl_kernel import causal_conv1d_fwd from sgl_kernel import causal_conv1d_fwd
from sgl_kernel import causal_conv1d_update as causal_conv1d_update_kernel from sgl_kernel import causal_conv1d_update as causal_conv1d_update_kernel
torch.ops.sgl_kernel.causal_conv1d_update torch.ops.sgl_kernel.causal_conv1d_update
_USE_TRITON = False _HAS_SGL_KERNEL = True
except (ImportError, AttributeError): except (ImportError, AttributeError):
from .causal_conv1d_triton import causal_conv1d_fn as _causal_conv1d_fn_triton _HAS_SGL_KERNEL = False
from .causal_conv1d_triton import (
causal_conv1d_update as _causal_conv1d_update_triton,
)
_USE_TRITON = True
def _get_seq_lens_cpu(query_start_loc, x):
if query_start_loc is not None:
return (query_start_loc[1:] - query_start_loc[:-1]).cpu().tolist()
return [x.shape[-1]]
def causal_conv1d_fn( def causal_conv1d_fn(
@@ -66,19 +69,20 @@ def causal_conv1d_fn(
out: (batch, dim, seqlen) out: (batch, dim, seqlen)
""" """
if _USE_TRITON: # Use Triton when: (1) sgl_kernel not available, or (2) input is
seq_lens_cpu = ( # non-contiguous and seq_lens_cpu is already pre-computed by caller.
(query_start_loc[1:] - query_start_loc[:-1]).cpu().tolist() # The Triton kernel accepts arbitrary strides, avoiding a .contiguous()
if query_start_loc is not None # copy that can cost >0.6 ms/layer on large prefill batches.
else [x.shape[-1]] use_triton = not _HAS_SGL_KERNEL or (x.stride(-1) != 1 and "seq_lens_cpu" in kwargs)
) if use_triton:
if "seq_lens_cpu" not in kwargs:
kwargs["seq_lens_cpu"] = _get_seq_lens_cpu(query_start_loc, x)
return _causal_conv1d_fn_triton( return _causal_conv1d_fn_triton(
x, x,
weight, weight,
bias, bias,
conv_states=conv_states, conv_states=conv_states,
query_start_loc=query_start_loc, query_start_loc=query_start_loc,
seq_lens_cpu=seq_lens_cpu,
cache_indices=cache_indices, cache_indices=cache_indices,
has_initial_state=has_initial_state, has_initial_state=has_initial_state,
activation=activation, activation=activation,
@@ -137,7 +141,8 @@ def causal_conv1d_update(
indices 0 and 3 indices 0 and 3
out: (batch, dim) or (batch, dim, seqlen) out: (batch, dim) or (batch, dim, seqlen)
""" """
if _USE_TRITON: use_triton = not _HAS_SGL_KERNEL
if use_triton:
return _causal_conv1d_update_triton( return _causal_conv1d_update_triton(
x, x,
conv_state, conv_state,
+2 -2
View File
@@ -118,7 +118,7 @@ def run_eval(args):
elif args.eval_name == "gpqa": elif args.eval_name == "gpqa":
from sglang.test.simple_eval_gpqa import GPQAEval from sglang.test.simple_eval_gpqa import GPQAEval
filename = ( filename = getattr(args, "dataset_path", None) or (
"https://openaipublic.blob.core.windows.net/simple-evals/gpqa_diamond.csv" "https://openaipublic.blob.core.windows.net/simple-evals/gpqa_diamond.csv"
) )
eval_obj = GPQAEval(filename, args.num_examples, args.num_threads) eval_obj = GPQAEval(filename, args.num_examples, args.num_threads)
@@ -130,7 +130,7 @@ def run_eval(args):
from sglang.test.simple_eval_longbench_v2 import LongBenchV2Eval from sglang.test.simple_eval_longbench_v2 import LongBenchV2Eval
# Default to HuggingFace dataset, can be overridden with --dataset-path # Default to HuggingFace dataset, can be overridden with --dataset-path
data_source = args.dataset_path data_source = getattr(args, "dataset_path", None)
categories = args.categories.split(",") if args.categories else None categories = args.categories.split(",") if args.categories else None
eval_obj = LongBenchV2Eval( eval_obj = LongBenchV2Eval(