[Config] Infer HiSparse attention config from HiSparseConnector (#57041)
Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai>
Nicolò Lucchesi committed
Sep 15, 2026 at 21:44 UTC
df42d112ee88dd4a9b64efbad55621af6a66a44b
3 files changed
+113
-2
tests/test_config.py
+102
@@ -337,6 +337,108 @@ def test_hisparse_rejects_non_cuda(monkeypatch):
337
VllmConfig(attention_config=AttentionConfig(hisparse_config=HiSparseConfig()))
338
339
340
+@pytest.mark.parametrize(
341
+ "kv_transfer_config",
342
+ [
343
+ KVTransferConfig(
344
+ kv_connector="HiSparseConnector",
345
+ kv_role="kv_both",
346
+ kv_connector_extra_config={"host_pool_gib": 128},
347
+ ),
348
+ KVTransferConfig(
349
+ kv_connector="MultiConnector",
350
+ kv_role="kv_both",
351
+ kv_connector_extra_config={
352
+ "connectors": [
353
+ {
354
+ "kv_connector": "OffloadingConnector",
355
+ "kv_role": "kv_both",
356
+ "kv_connector_extra_config": {"cpu_bytes_to_use": 1 << 30},
357
+ },
358
+ {
359
+ "kv_connector": "HiSparseConnector",
360
+ "kv_role": "kv_both",
361
+ "kv_connector_extra_config": {"host_pool_gib": 128},
362
+ },
363
+ ]
364
+ },
365
+ ),
366
+ KVTransferConfig(
367
+ kv_connector="MultiConnector",
368
+ kv_role="kv_consumer",
369
+ kv_connector_extra_config={
370
+ "connectors": [
371
+ {"kv_connector": "NixlConnector", "kv_role": "kv_consumer"},
372
+ {
373
+ "kv_connector": "HiSparseConnector",
374
+ "kv_role": "kv_both",
375
+ "kv_connector_extra_config": {"host_pool_gib": 128},
376
+ },
377
+ ]
378
+ },
379
+ ),
380
+ ],
381
+ ids=["standalone", "multi-connector", "pd-decode"],
382
+)
383
+def test_hisparse_connector_implies_attention_config(monkeypatch, kv_transfer_config):
384
+ monkeypatch.setattr(current_platform, "is_cuda", lambda: True)
385
+ monkeypatch.setattr("vllm.config.vllm.HAS_TRITON", True)
386
+ config = VllmConfig(
387
+ kv_transfer_config=kv_transfer_config,
388
+ # Skip the HMA auto-detect block: it imports the connector class,
389
+ # which pulls the platform's compiled attention extensions.
390
+ scheduler_config=SchedulerConfig(
391
+ max_model_len=2048,
392
+ is_encoder_decoder=False,
393
+ disable_hybrid_kv_cache_manager=False,
394
+ ),
395
+ )
396
+ assert isinstance(config.attention_config.hisparse_config, HiSparseConfig)
397
+
398
+
399
+def test_hisparse_connector_preserves_explicit_attention_config(monkeypatch):
400
+ monkeypatch.setattr(current_platform, "is_cuda", lambda: True)
401
+ monkeypatch.setattr("vllm.config.vllm.HAS_TRITON", True)
402
+ config = VllmConfig(
403
+ attention_config=AttentionConfig(
404
+ hisparse_config=HiSparseConfig(device_buffer_size=512)
405
+ ),
406
+ kv_transfer_config=KVTransferConfig(
407
+ kv_connector="HiSparseConnector",
408
+ kv_role="kv_both",
409
+ kv_connector_extra_config={"host_pool_gib": 128},
410
+ ),
411
+ scheduler_config=SchedulerConfig(
412
+ max_model_len=2048,
413
+ is_encoder_decoder=False,
414
+ disable_hybrid_kv_cache_manager=False,
415
+ ),
416
+ )
417
+ assert config.attention_config.hisparse_config.device_buffer_size == 512
418
+
419
+
420
+def test_hisparse_connector_without_cuda_still_rejected(monkeypatch):
421
+ monkeypatch.setattr(current_platform, "is_cuda", lambda: False)
422
+ with pytest.raises(ValueError, match="requires NVIDIA CUDA"):
423
+ VllmConfig(
424
+ kv_transfer_config=KVTransferConfig(
425
+ kv_connector="HiSparseConnector",
426
+ kv_role="kv_both",
427
+ kv_connector_extra_config={"host_pool_gib": 128},
428
+ )
429
+ )
430
+
431
+
432
+def test_no_hisparse_connector_keeps_attention_config_unset(monkeypatch):
433
+ monkeypatch.setattr(current_platform, "is_cuda", lambda: True)
434
+ config = VllmConfig(
435
+ kv_transfer_config=KVTransferConfig(
436
+ kv_connector="OffloadingConnector", kv_role="kv_both"
437
+ )
438
+ )
439
+ assert config.attention_config.hisparse_config is None
440
+
441
+
442
def test_rocm_keeps_compiled_deepseek_defaults(monkeypatch):
443
"""ROCm keeps the DSA models (DeepSeek V3.2/V4, GLM-5.2) on their compiled
444
MRV1 paths and off breakable cudagraphs by default."""
vllm/config/attention.py
+3
-1
@@ -88,7 +88,9 @@ class AttentionConfig:
88
89
hisparse_config: HiSparseConfig | None = None
90
"""HiSparse host-resident KV configuration. Setting this enables experimental
91
- Model Runner V2-only HiSparse sparse-MLA decode hot-buffering."""
91
+ Model Runner V2-only HiSparse sparse-MLA decode hot-buffering. It is inferred
92
+ with defaults when HiSparseConnector is configured (directly or via
93
+ MultiConnector); set it explicitly only to tune its fields."""
94
95
use_non_causal: bool = False
96
"""Whether to use non-causal (bidirectional) attention."""
vllm/config/vllm.py
+8
-1
@@ -27,7 +27,7 @@ from vllm.triton_utils import HAS_TRITON
27
from vllm.utils import random_uuid
28
from vllm.utils.hashing import safe_hash
29
30
-from .attention import AttentionConfig
30
+from .attention import AttentionConfig, HiSparseConfig
31
from .cache import CacheConfig
32
from .compilation import CompilationConfig, CompilationMode, CUDAGraphMode
33
from .device import DeviceConfig
@@ -1630,6 +1630,13 @@ class VllmConfig:
1630
self._maybe_disable_dynamic_sd_for_data_parallel()
1631
self._maybe_override_dynamic_sd_cudagraph_mode()
1632
1633
+ if (
1634
+ self.attention_config.hisparse_config is None
1635
+ and self.kv_transfer_config is not None
1636
+ and self.kv_transfer_config.has_connector("HiSparseConnector")
1637
+ ):
1638
+ self.attention_config.hisparse_config = HiSparseConfig()
1639
+
1640
if self.attention_config.hisparse_config is not None:
1641
if not current_platform.is_cuda():
1642
raise ValueError("HiSparse currently requires NVIDIA CUDA.")