Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions benchmarks/single_node/agentic/dsv4_fp4_b200_vllm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,6 @@ install_agentic_deps

export AIPERF_AGENTIC_CACHE_WARMUP_DURATION=600

# vLLM v0.22.1 can ship CUTLASS DSL 4.5.2 with stale native MLIR bindings,
# which fails DSV4 indexer compilation with mlir_global_dtors(..., data).
# Reinstall the matching native wheel until NVIDIA/cutlass#3259 is resolved.
agentic_pip_install --quiet --force-reinstall --no-deps \
'nvidia-cutlass-dsl-libs-cu13==4.5.2'

# vllm-project/router expands the one HTTP backend into one logical worker per
# DP rank and sends X-data-parallel-rank on forwarded requests. aiperf's
# X-Correlation-ID is stable for every turn of a conversation; alias it to the
Expand Down Expand Up @@ -147,16 +141,22 @@ EOF
cat "$MOONCAKE_MASTER_LOG" >&2
exit 1
fi
unset VLLM_USE_SIMPLE_KV_OFFLOAD
OFFLOAD_ARGS=(
--kv-transfer-config
'{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_both","kv_connector_extra_config":{"load_async":true}}'
'{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_both"}'
)

python3 /workspace/benchmarks/single_node/agentic/patch_vllm_0_24_async_kv_deadlock.py
fi

PARALLEL_ARGS=(--tensor-parallel-size "$TP" --data-parallel-size 1)
if [ "$DP_ATTENTION" = "true" ]; then
PARALLEL_ARGS=(--tensor-parallel-size 1 --data-parallel-size "$TP")
# Each DEP rank owns one GPU, so keep its worker in the EngineCore process.
PARALLEL_ARGS=(
--tensor-parallel-size 1
--data-parallel-size "$TP"
--distributed-executor-backend uni
)
fi

EP_ARGS=()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env python3
"""Backport vLLM PR #45406 to the v0.24.0 scheduler."""

from importlib.metadata import distribution
from pathlib import Path


OLD_BLOCK = """\
if request.has_encoder_inputs:
self.encoder_cache_manager.free(request)
break
"""

NEW_BLOCK = """\
if request.has_encoder_inputs:
self.encoder_cache_manager.free(request)
if self.running:
# Running requests will free blocks when they
# complete; stop here to preserve queue-order
# admission.
break
# Nothing is running, so no future event frees blocks and
# stopping at this request would freeze this state
# permanently. Requests behind this one may hold blocks
# while parked (async KV loads in WAITING_FOR_REMOTE_KVS)
# and are only promoted when this traversal reaches them.
# Keep scanning so they can be promoted, scheduled, and
# eventually free the blocks this request needs.
# See https://github.com/vllm-project/vllm/issues/45388
request_queue.pop_request()
step_skipped_waiting.prepend_request(request)
continue
"""


def main() -> None:
vllm_distribution = distribution("vllm")
installed_version = vllm_distribution.version
if installed_version != "0.24.0":
raise RuntimeError(
f"Expected vLLM 0.24.0, found {installed_version}; "
"review whether PR #45406 is still needed"
)

scheduler_path = Path(
vllm_distribution.locate_file("vllm/v1/core/sched/scheduler.py")
)
source = scheduler_path.read_text()
if NEW_BLOCK in source:
print("vLLM async-KV scheduler fix already present")
return
if source.count(OLD_BLOCK) != 1:
raise RuntimeError(
f"Could not uniquely locate the vLLM 0.24.0 scheduler block in "
f"{scheduler_path}"
)

scheduler_path.write_text(source.replace(OLD_BLOCK, NEW_BLOCK))
print(f"Applied vLLM PR #45406 scheduler fix to {scheduler_path}")


if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion configs/nvidia-master.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1763,7 +1763,7 @@ dsv4-fp4-b200-vllm:
- { tp: 8, ep: 8, dp-attn: true, conc-start: 64, conc-end: 1024 }

dsv4-fp4-b200-vllm-agentic:
image: vllm/vllm-openai:v0.23.0
image: vllm/vllm-openai:v0.24.0
model: deepseek-ai/DeepSeek-V4-Pro
model-prefix: dsv4
runner: cluster:b200-dgxc
Expand Down
14 changes: 13 additions & 1 deletion utils/matrix_logic/generate_sweep_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ def generate_full_sweep(args, all_config_data, runner_data):
"""Generate full sweep configurations with optional filtering.

Supports filtering by model prefix, precision, framework, runner type, sequence lengths,
and max concurrency.
KV offloading mode, and concurrency.

All filters are optional - can generate sweeps for all configs or filter by specific criteria.

Expand Down Expand Up @@ -597,6 +597,11 @@ def generate_full_sweep(args, all_config_data, runner_data):
dp_attn = bmk.get(Fields.DP_ATTN.value)
kv_offloading = bmk[Fields.KV_OFFLOADING.value]
kv_offload_backend = bmk.get(Fields.KV_OFFLOAD_BACKEND.value)
if (
getattr(args, "kv_offloading", None)
and kv_offloading not in args.kv_offloading
):
continue
total_cpu_dram_gb = (
0
if is_multinode
Expand Down Expand Up @@ -1081,6 +1086,13 @@ def main():
required=False,
help='Runner type(s) to filter by (e.g., h200, h100) (optional, can specify multiple)'
)
full_sweep_parser.add_argument(
'--kv-offloading',
nargs='+',
choices=['none', 'dram'],
required=False,
help='Agentic KV offloading mode(s) to include (optional, can specify multiple)'
)
full_sweep_parser.add_argument(
'--seq-lens',
nargs='+',
Expand Down
50 changes: 50 additions & 0 deletions utils/matrix_logic/test_generate_sweep_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,56 @@ def test_filter_by_runner_type(self, sample_single_node_config, sample_runner_co
)
assert len(result) == 0

@pytest.mark.parametrize("mode", ["none", "dram"])
def test_filter_agentic_by_kv_offloading(
self,
mode,
sample_runner_config,
full_sweep_args_single_node,
):
"""KV offloading filter should retain only matching AgentX entries."""
config = {
"dsv4-fp4-b200-vllm-agentic": {
"image": "vllm/vllm-openai:v0.24.0",
"model": "deepseek-ai/DeepSeek-V4-Pro",
"model-prefix": "dsv4",
"precision": "fp4",
"framework": "vllm",
"runner": "cluster:b200-dgxc",
"multinode": False,
"scenarios": {
"agentic-coding": [{
"dram-utilization": 0.80,
"search-space": [
{
"tp": 8,
"kv-offloading": "none",
"conc-list": [8],
},
{
"tp": 8,
"kv-offloading": "dram",
"kv-offload-backend": "mooncake",
"conc-list": [8],
},
],
}],
},
},
}
full_sweep_args_single_node.scenario_type = ["agentic-coding"]
full_sweep_args_single_node.kv_offloading = [mode]

result = generate_full_sweep(
full_sweep_args_single_node,
config,
sample_runner_config,
)

assert len(result) == 1
assert result[0]["kv-offloading"] == mode
assert ("kv-offload-backend" in result[0]) is (mode == "dram")

def test_invalid_runner_type_raises_error(self, sample_single_node_config, sample_runner_config, full_sweep_args_single_node):
"""Invalid runner type should raise ValueError."""
full_sweep_args_single_node.runner_type = ["invalid_runner"]
Expand Down