[Diffusion][HunyuanImage3] Add request paged prefix caching (#7719)
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
This commit is contained in:
1 parent
9a1a05facd
commit
205aa01c7b
49 files changed
+2889
-127
No files matched your search
@@ -113,7 +113,7 @@ class _FakeLayer:
|
||||
self.head_size_v = 4
|
||||
self.spec = _FakeSpec(non_causal=non_causal)
|
||||
self.updates: list[tuple[torch.Tensor, torch.Tensor, torch.Tensor]] = []
|
||||
self.calls: list[tuple[torch.Tensor, torch.Tensor, torch.Tensor, object]] = []
|
||||
self.calls: list[tuple[torch.Tensor, torch.Tensor, torch.Tensor, _FakeNativeMetadata]] = []
|
||||
self.native_events: list[str] = []
|
||||
self.layer_name = "layer-0"
|
||||
self.kv_cache = object()
|
||||
@@ -122,6 +122,8 @@ class _FakeLayer:
|
||||
|
||||
|
||||
class _FakeNativeImpl:
|
||||
vllm_flash_attn_version: int
|
||||
|
||||
def __init__(self, layer: _FakeLayer) -> None:
|
||||
self.layer = layer
|
||||
|
||||
@@ -143,7 +145,7 @@ class _FakeNativeImpl:
|
||||
key: torch.Tensor,
|
||||
value: torch.Tensor,
|
||||
_kv_cache,
|
||||
metadata: object,
|
||||
metadata: _FakeNativeMetadata,
|
||||
output: torch.Tensor,
|
||||
) -> torch.Tensor:
|
||||
self.layer.native_events.append("forward")
|
||||
@@ -202,7 +204,7 @@ def _make_adapter(
|
||||
|
||||
config = SimpleNamespace(
|
||||
name="vllm-config",
|
||||
model_config=SimpleNamespace(dtype=torch.float32),
|
||||
model_config=SimpleNamespace(dtype=torch.float32, rswa_window=None),
|
||||
)
|
||||
adapter = DiffusionPagedAttentionAdapter(
|
||||
vllm_config=config,
|
||||
@@ -1222,9 +1224,15 @@ def test_row_contract_rejects_invalid_identity_or_span(kwargs: dict, message: st
|
||||
DiffusionPagedAttentionRow(**values)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("pcp_size", [1, 2])
|
||||
@pytest.mark.parametrize("selection_fails", [False, True])
|
||||
def test_layer_adapter_accepts_platform_native_backend_and_uses_rank_local_heads(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
pcp_size: int,
|
||||
selection_fails: bool,
|
||||
) -> None:
|
||||
from vllm.v1.attention import selector
|
||||
|
||||
selected_backends = []
|
||||
specialized_backends = []
|
||||
impl_cls = Mock(return_value=SimpleNamespace(forward=Mock(), do_kv_cache_update=Mock()))
|
||||
@@ -1237,28 +1245,39 @@ def test_layer_adapter_accepts_platform_native_backend_and_uses_rank_local_heads
|
||||
|
||||
original_backend_per_kind = {"full": object()}
|
||||
config = SimpleNamespace(
|
||||
attention_config=SimpleNamespace(backend=None, backend_per_kind=original_backend_per_kind),
|
||||
parallel_config=SimpleNamespace(prefill_context_parallel_size=2),
|
||||
model_config=SimpleNamespace(dtype=torch.float16),
|
||||
cache_config=SimpleNamespace(cache_dtype="auto"),
|
||||
attention_config=SimpleNamespace(backend=None, backend_per_kind=original_backend_per_kind, use_non_causal=True),
|
||||
parallel_config=SimpleNamespace(prefill_context_parallel_size=pcp_size, decode_context_parallel_size=1),
|
||||
model_config=SimpleNamespace(dtype=torch.float16, rswa_window=None),
|
||||
cache_config=SimpleNamespace(cache_dtype="auto", user_specified_block_size=False),
|
||||
kv_transfer_config=None,
|
||||
speculative_config=None,
|
||||
)
|
||||
|
||||
def select_backend(**_kwargs):
|
||||
selected_backends.append(
|
||||
(
|
||||
config.attention_config.backend,
|
||||
config.attention_config.backend_per_kind,
|
||||
config.parallel_config.prefill_context_parallel_size,
|
||||
)
|
||||
)
|
||||
def select_backend(*, backend, attn_selector_config, num_heads):
|
||||
# Exercise the real 0.29 selector, replacing only platform resolution.
|
||||
# Ulysses has already gathered tokens and sharded heads before the
|
||||
# native kernel; the MoE PCP mapping must not request PCP attention.
|
||||
assert not attn_selector_config.use_pcp
|
||||
assert not attn_selector_config.use_dcp
|
||||
assert attn_selector_config.use_non_causal
|
||||
assert num_heads == 4
|
||||
selected_backends.append((backend, config.attention_config.backend_per_kind))
|
||||
if selection_fails:
|
||||
raise ValueError("test backend unavailable")
|
||||
return native_backend
|
||||
|
||||
monkeypatch.setattr(adapter_module, "get_attn_backend", select_backend)
|
||||
monkeypatch.setattr("vllm.config.get_current_vllm_config", lambda: config)
|
||||
monkeypatch.setattr(selector, "_cached_get_attn_backend", select_backend)
|
||||
monkeypatch.setattr(adapter_module, "set_current_vllm_config", lambda _config: nullcontext())
|
||||
|
||||
def specialize_backend(backend, *, ulysses_degree):
|
||||
specialized_backends.append((backend, ulysses_degree))
|
||||
return backend
|
||||
|
||||
monkeypatch.setattr(
|
||||
adapter_module.current_omni_platform,
|
||||
"get_diffusion_paged_kv_attn_backend",
|
||||
lambda backend, *, ulysses_degree: specialized_backends.append((backend, ulysses_degree)) or backend,
|
||||
specialize_backend,
|
||||
)
|
||||
layer = SimpleNamespace(num_heads=8, softmax_scale=0.125)
|
||||
spec = FullAttentionSpec(
|
||||
@@ -1269,7 +1288,7 @@ def test_layer_adapter_accepts_platform_native_backend_and_uses_rank_local_heads
|
||||
non_causal=True,
|
||||
)
|
||||
|
||||
native_layer = adapter_module.DiffusionPagedAttentionLayerAdapter(
|
||||
kwargs = dict(
|
||||
layer_name="layer-0",
|
||||
layer=layer,
|
||||
spec=spec,
|
||||
@@ -1277,12 +1296,21 @@ def test_layer_adapter_accepts_platform_native_backend_and_uses_rank_local_heads
|
||||
device=torch.device("cpu"),
|
||||
ulysses_degree=2,
|
||||
)
|
||||
if selection_fails:
|
||||
with pytest.raises(ValueError, match="test backend unavailable"):
|
||||
adapter_module.DiffusionPagedAttentionLayerAdapter(**kwargs)
|
||||
else:
|
||||
native_layer = adapter_module.DiffusionPagedAttentionLayerAdapter(**kwargs)
|
||||
|
||||
assert selected_backends == [(adapter_module.AttentionBackendEnum.FLASH_ATTN, {}, 1)]
|
||||
assert specialized_backends == [(native_backend, 2)]
|
||||
assert selected_backends == [(adapter_module.AttentionBackendEnum.FLASH_ATTN, {})]
|
||||
assert config.attention_config.backend is None
|
||||
assert config.attention_config.backend_per_kind is original_backend_per_kind
|
||||
assert config.parallel_config.prefill_context_parallel_size == 2
|
||||
assert config.parallel_config.prefill_context_parallel_size == pcp_size
|
||||
if selection_fails:
|
||||
assert not specialized_backends
|
||||
impl_cls.assert_not_called()
|
||||
return
|
||||
assert specialized_backends == [(native_backend, 2)]
|
||||
assert native_layer.num_heads == 4
|
||||
assert native_layer.num_kv_heads == 2
|
||||
assert native_layer.spec.num_kv_heads == 2
|
||||
@@ -1432,7 +1460,12 @@ def test_omni_attention_keeps_dense_kernel_without_active_adapter() -> None:
|
||||
layer._no_parallel_strategy = object()
|
||||
layer._get_active_parallel_strategy = lambda: Strategy()
|
||||
layer._with_kv_cache_dtype = lambda metadata: metadata
|
||||
layer._run_local_attention = lambda query, _key, _value, _metadata: events.append("dense") or query
|
||||
|
||||
def run_local_attention(query, _key, _value, _metadata):
|
||||
events.append("dense")
|
||||
return query
|
||||
|
||||
layer._run_local_attention = run_local_attention
|
||||
qkv = torch.zeros(1, 2, 2, 4)
|
||||
|
||||
assert not layer.is_paged_kv_active()
|
||||
|
||||
Reference in new issue
Block a user