[Feature] npu support enable_torch_compile for torchair backend (#13410)
Co-authored-by: ZhengdQin <zhengdqin@gmail.com>
This commit is contained in:
@@ -248,6 +248,7 @@ class AscendAttnBackend(AttentionBackend):
|
||||
self.req_to_token = model_runner.req_to_token_pool.req_to_token
|
||||
self.graph_mode = False
|
||||
self.use_fia = get_bool_env_var("ASCEND_USE_FIA", "False")
|
||||
self.enable_torch_compile = model_runner.server_args.enable_torch_compile
|
||||
self.speculative_num_draft_tokens = (
|
||||
model_runner.server_args.speculative_num_draft_tokens
|
||||
)
|
||||
@@ -1255,7 +1256,7 @@ class AscendAttnBackend(AttentionBackend):
|
||||
topk_indices,
|
||||
)
|
||||
|
||||
if self.graph_mode:
|
||||
if self.graph_mode and (not self.enable_torch_compile):
|
||||
return self.forward_decode_graph(
|
||||
q,
|
||||
k,
|
||||
@@ -1276,6 +1277,12 @@ class AscendAttnBackend(AttentionBackend):
|
||||
k_cache = forward_batch.token_to_kv_pool.get_key_buffer(layer.layer_id)
|
||||
v_cache = forward_batch.token_to_kv_pool.get_value_buffer(layer.layer_id)
|
||||
if self.use_fia:
|
||||
if self.forward_metadata.seq_lens_cpu_int is None:
|
||||
actual_seq_len_kv = self.forward_metadata.seq_lens_cpu_list
|
||||
else:
|
||||
actual_seq_len_kv = (
|
||||
self.forward_metadata.seq_lens_cpu_int.cpu().int().tolist()
|
||||
)
|
||||
attn_output, _ = torch.ops.npu.npu_fused_infer_attention_score(
|
||||
q.view(
|
||||
forward_batch.batch_size,
|
||||
@@ -1295,7 +1302,7 @@ class AscendAttnBackend(AttentionBackend):
|
||||
atten_mask=None,
|
||||
block_size=self.page_size,
|
||||
block_table=self.forward_metadata.block_tables,
|
||||
actual_seq_lengths_kv=self.forward_metadata.seq_lens_cpu_int,
|
||||
actual_seq_lengths_kv=actual_seq_len_kv,
|
||||
scale=layer.scaling,
|
||||
)
|
||||
else:
|
||||
|
||||
@@ -18,16 +18,24 @@ from __future__ import annotations
|
||||
import logging
|
||||
import os
|
||||
import threading
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Dict, Optional, Union
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
|
||||
import sglang
|
||||
from sglang.srt.configs.model_config import AttentionArch, is_deepseek_nsa
|
||||
from sglang.srt.distributed.parallel_state import GroupCoordinator
|
||||
from sglang.srt.layers.dp_attention import get_attention_tp_size
|
||||
from sglang.srt.model_executor.cuda_graph_runner import CudaGraphRunner
|
||||
from sglang.srt.utils import is_npu
|
||||
from sglang.srt.utils import (
|
||||
empty_context,
|
||||
get_bool_env_var,
|
||||
get_compiler_backend,
|
||||
is_npu,
|
||||
)
|
||||
|
||||
is_npu = is_npu()
|
||||
|
||||
@@ -44,15 +52,36 @@ from sglang.srt.layers.logits_processor import LogitsProcessorOutput
|
||||
from sglang.srt.model_executor.forward_batch_info import ForwardBatch, PPProxyTensors
|
||||
|
||||
|
||||
@contextmanager
|
||||
def patch_model_npu(
|
||||
model: torch.nn.Module,
|
||||
enable_compile: bool,
|
||||
num_tokens: int,
|
||||
tp_group: GroupCoordinator,
|
||||
):
|
||||
if enable_compile:
|
||||
backend = get_compiler_backend("npugraph_ex")
|
||||
yield torch.compile(
|
||||
torch.no_grad()(model.forward),
|
||||
fullgraph=True,
|
||||
dynamic=False,
|
||||
backend=backend,
|
||||
)
|
||||
else:
|
||||
yield model.forward
|
||||
|
||||
|
||||
class NPUGraphRunner(CudaGraphRunner):
|
||||
"""A NPUGraphRunner runs the forward pass of a model with npu graph and torch.compile."""
|
||||
|
||||
def __init__(self, model_runner: ModelRunner):
|
||||
sglang.srt.model_executor.cuda_graph_runner.patch_model = patch_model_npu
|
||||
super().__init__(model_runner)
|
||||
self.update_attr_name = None
|
||||
self.update_attr_type = None
|
||||
self.model_runner = model_runner
|
||||
self._init_arch_map()
|
||||
self.use_fia = get_bool_env_var("ASCEND_USE_FIA", "False")
|
||||
|
||||
def _init_arch_map(self):
|
||||
self.attr_name: Dict[str, str] = {
|
||||
@@ -68,7 +97,12 @@ class NPUGraphRunner(CudaGraphRunner):
|
||||
return torch.npu.NPUGraph()
|
||||
|
||||
def _capture_graph(self, graph, pool, stream, run_once_fn):
|
||||
with torch.npu.graph(
|
||||
if self.enable_torch_compile:
|
||||
skip_guard_context = torch.compiler.set_stance(skip_guard_eval_unsafe=True)
|
||||
else:
|
||||
skip_guard_context = empty_context()
|
||||
|
||||
with skip_guard_context, torch.npu.graph(
|
||||
graph,
|
||||
pool=pool,
|
||||
stream=stream,
|
||||
@@ -81,6 +115,7 @@ class NPUGraphRunner(CudaGraphRunner):
|
||||
if (
|
||||
self.bs < get_attention_tp_size()
|
||||
or forward_batch.forward_mode.is_target_verify()
|
||||
or self.use_fia
|
||||
):
|
||||
return self.attr_name[AttentionArch.MLA]
|
||||
return self.attr_name[model_runner.model_config.attention_arch]
|
||||
@@ -89,6 +124,7 @@ class NPUGraphRunner(CudaGraphRunner):
|
||||
if (
|
||||
self.bs < get_attention_tp_size()
|
||||
or forward_batch.forward_mode.is_target_verify()
|
||||
or self.use_fia
|
||||
):
|
||||
return self.attr_type[AttentionArch.MLA]
|
||||
return self.attr_type[model_runner.model_config.attention_arch]
|
||||
|
||||
@@ -9,6 +9,7 @@ from sglang.srt.mem_cache.memory_pool import (
|
||||
MLATokenToKVPool,
|
||||
get_tensor_size_bytes,
|
||||
)
|
||||
from sglang.srt.utils import get_bool_env_var
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sglang.srt.layers.radix_attention import RadixAttention
|
||||
@@ -16,6 +17,37 @@ if TYPE_CHECKING:
|
||||
|
||||
class NPUMHATokenToKVPool(MHATokenToKVPool):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
size: int,
|
||||
page_size: int,
|
||||
dtype: torch.dtype,
|
||||
head_num: int,
|
||||
head_dim: int,
|
||||
layer_num: int,
|
||||
device: str,
|
||||
enable_memory_saver: bool,
|
||||
start_layer: Optional[int] = None,
|
||||
end_layer: Optional[int] = None,
|
||||
enable_alt_stream: bool = True,
|
||||
enable_kv_cache_copy: bool = False,
|
||||
):
|
||||
self.use_fia = get_bool_env_var("ASCEND_USE_FIA", "False")
|
||||
super().__init__(
|
||||
size,
|
||||
page_size,
|
||||
dtype,
|
||||
head_num,
|
||||
head_dim,
|
||||
layer_num,
|
||||
device,
|
||||
enable_memory_saver,
|
||||
start_layer,
|
||||
end_layer,
|
||||
enable_alt_stream,
|
||||
enable_kv_cache_copy,
|
||||
)
|
||||
|
||||
def _create_buffers(self):
|
||||
with self.memory_saver_adapter.region(GPU_MEMORY_TYPE_KV_CACHE):
|
||||
# [size, head_num, head_dim] for each layer
|
||||
@@ -37,6 +69,19 @@ class NPUMHATokenToKVPool(MHATokenToKVPool):
|
||||
self.k_buffer = self.kv_buffer[0]
|
||||
self.v_buffer = self.kv_buffer[1]
|
||||
|
||||
if self.use_fia:
|
||||
self.k_buffer = []
|
||||
self.v_buffer = []
|
||||
for i in range(self.layer_num):
|
||||
k_buffer_layer = self.kv_buffer[0][i].view(
|
||||
-1, 1, self.head_num, self.head_dim
|
||||
)
|
||||
v_buffer_layer = self.kv_buffer[1][i].view(
|
||||
-1, 1, self.head_num, self.head_dim
|
||||
)
|
||||
self.k_buffer.append(k_buffer_layer)
|
||||
self.v_buffer.append(v_buffer_layer)
|
||||
|
||||
# for disagg
|
||||
def get_contiguous_buf_infos(self):
|
||||
# layer_num x [seq_len, head_num, head_dim]
|
||||
@@ -89,18 +134,34 @@ class NPUMHATokenToKVPool(MHATokenToKVPool):
|
||||
if self.store_dtype != self.dtype:
|
||||
cache_k = cache_k.view(self.store_dtype)
|
||||
cache_v = cache_v.view(self.store_dtype)
|
||||
loc = loc.to(torch.int32)
|
||||
torch_npu._npu_reshape_and_cache(
|
||||
key=cache_k,
|
||||
value=cache_v,
|
||||
key_cache=self.k_buffer[layer_id - self.start_layer].view(
|
||||
-1, self.page_size, self.head_num, self.head_dim
|
||||
),
|
||||
value_cache=self.v_buffer[layer_id - self.start_layer].view(
|
||||
-1, self.page_size, self.head_num, self.head_dim
|
||||
),
|
||||
slot_indices=loc,
|
||||
)
|
||||
|
||||
if self.use_fia:
|
||||
k_buffer_layer = self.k_buffer[layer_id - self.start_layer]
|
||||
v_buffer_layer = self.v_buffer[layer_id - self.start_layer]
|
||||
|
||||
torch_npu.npu_scatter_nd_update_(
|
||||
k_buffer_layer,
|
||||
loc.view(-1, 1),
|
||||
cache_k.view(-1, 1, self.head_num, self.head_dim),
|
||||
)
|
||||
torch_npu.npu_scatter_nd_update_(
|
||||
v_buffer_layer,
|
||||
loc.view(-1, 1),
|
||||
cache_v.view(-1, 1, self.head_num, self.head_dim),
|
||||
)
|
||||
else:
|
||||
loc = loc.to(torch.int32)
|
||||
torch_npu._npu_reshape_and_cache(
|
||||
key=cache_k,
|
||||
value=cache_v,
|
||||
key_cache=self.k_buffer[layer_id - self.start_layer].view(
|
||||
-1, self.page_size, self.head_num, self.head_dim
|
||||
),
|
||||
value_cache=self.v_buffer[layer_id - self.start_layer].view(
|
||||
-1, self.page_size, self.head_num, self.head_dim
|
||||
),
|
||||
slot_indices=loc,
|
||||
)
|
||||
|
||||
|
||||
class NPUMLATokenToKVPool(MLATokenToKVPool):
|
||||
|
||||
@@ -269,27 +269,22 @@ class RotaryEmbedding(CustomOp):
|
||||
fused_set_kv_buffer_arg is None
|
||||
), "fused_set_kv_buffer_arg is not supported for npu implementation"
|
||||
|
||||
if get_bool_env_var("SGLANG_ENABLE_TORCH_COMPILE"):
|
||||
return self.forward_native(
|
||||
positions, query, key, offsets, fused_set_kv_buffer_arg
|
||||
)
|
||||
else:
|
||||
rotary_mode = "half"
|
||||
if self.is_neox_style:
|
||||
rotary_mode = "half"
|
||||
if self.is_neox_style:
|
||||
rotary_mode = "half"
|
||||
else:
|
||||
rotary_mode = "interleave"
|
||||
mrope_section = [0, 0, 0]
|
||||
query_out, key_out = torch_npu.npu_mrope(
|
||||
positions,
|
||||
query,
|
||||
key,
|
||||
self.cos_sin_cache,
|
||||
self.head_size,
|
||||
mrope_section=mrope_section,
|
||||
rotary_mode=rotary_mode,
|
||||
)
|
||||
return query_out, key_out
|
||||
else:
|
||||
rotary_mode = "interleave"
|
||||
mrope_section = [0, 0, 0]
|
||||
query_out, key_out = torch_npu.npu_mrope(
|
||||
positions,
|
||||
query,
|
||||
key,
|
||||
self.cos_sin_cache,
|
||||
self.head_size,
|
||||
mrope_section=mrope_section,
|
||||
rotary_mode=rotary_mode,
|
||||
)
|
||||
return query_out, key_out
|
||||
|
||||
def forward_cpu(
|
||||
self,
|
||||
|
||||
@@ -1933,16 +1933,7 @@ def get_device_capability(device_id: int = 0) -> Tuple[int, int]:
|
||||
return major, minor
|
||||
|
||||
|
||||
def get_npu_compiler_config():
|
||||
config = {
|
||||
"frozen_parameter": True,
|
||||
"tiling_schedule_optimize": True,
|
||||
"topology_sorting_strategy": "StableRDFS",
|
||||
}
|
||||
return config
|
||||
|
||||
|
||||
def get_compiler_backend() -> str:
|
||||
def get_compiler_backend(mode=None) -> str:
|
||||
if hasattr(torch, "hpu") and torch.hpu.is_available():
|
||||
return "hpu_backend"
|
||||
|
||||
@@ -1957,10 +1948,10 @@ def get_compiler_backend() -> str:
|
||||
"Please install torchair for torch.compile support on NPU."
|
||||
)
|
||||
compiler_config = CompilerConfig()
|
||||
predefined_config = get_npu_compiler_config()
|
||||
for k, v in predefined_config.items():
|
||||
setattr(compiler_config.experimental_config, k, v)
|
||||
|
||||
compiler_config.mode = "max-autotune"
|
||||
if mode == "npugraph_ex":
|
||||
compiler_config.mode = "reduce-overhead"
|
||||
compiler_config.debug.run_eagerly = True
|
||||
npu_backend = torchair.get_npu_backend(compiler_config=compiler_config)
|
||||
return npu_backend
|
||||
|
||||
|
||||
Reference in New Issue
Block a user