Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ base:
resources:
gpu_type: b300
gpus_per_node: 8
srun_options:
mpi: pmix
frontend:
type: sglang
enable_multiple_frontends: false
Expand Down Expand Up @@ -43,11 +45,12 @@ base:
stream-interval: 50
scheduler-recv-interval: 10
tokenizer-worker-num: 6
tokenizer-path: Qwen/Qwen3.5-397B-A17B-FP8
tokenizer-path: /model
context-length: 9236
enable-metrics: false
env:
PYTHONNOUSERSITE: '1'
SGLANG_ENABLE_JIT_DEEPGEMM: '0'
benchmark:
type: custom
command: bash /infmax-workspace/benchmarks/single_node/srt_fixed_sequence.sh
Expand All @@ -56,13 +59,13 @@ base:
ISL: '8192'
OSL: '1024'
RANDOM_RANGE_RATIO: '0.8'
USE_CHAT_TEMPLATE: 'false'
USE_CHAT_TEMPLATE: 'true'
zip_override_concurrency:
roles:
agg:
args:
cuda-graph-max-bs: [4, 8, 16, 32, 64, 128, 256]
max-running-requests: [4, 8, 16, 32, 64, 128, 256]
cuda-graph-max-bs: [1, 2, 4, 8, 16, 32, 64, 128, 256]
max-running-requests: [1, 2, 4, 8, 16, 32, 64, 128, 256]
benchmark:
env:
CONC: ['4', '8', '16', '32', '64', '128', '256']
CONC: ['1', '2', '4', '8', '16', '32', '64', '128', '256']
3 changes: 2 additions & 1 deletion configs/nvidia-master.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1309,10 +1309,11 @@ qwen3.5-fp8-b300-sglang:
fixed-seq-len:
- isl: 8192
osl: 1024
require-power: true
search-space:
- tp: 4
ep: 1
conc-start: 4
conc-start: 1
conc-end: 256
srt-recipe: benchmarks/single_node/srt-slurm-recipes/qwen3.5/sglang/b300-fp8/8k1k.yaml

Expand Down
27 changes: 26 additions & 1 deletion infx/srt_slurm/single_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ def select_recipe(config: str, environment: Mapping[str, str]) -> tuple[str, dic
return matches[0]


def _qwen35_b300_fp8(recipe: dict[str, Any], environment: Mapping[str, str]) -> bool:
"""Preserve the established Qwen B300 workload and diagnostic settings."""
return (
recipe["model"]["path"] == "hf:Qwen/Qwen3.5-397B-A17B-FP8"
and recipe["model"]["precision"] == "fp8"
and recipe["resources"].get("gpu_type") == "b300"
and environment["FRAMEWORK"] == "sglang"
and environment["SPEC_DECODING"] == "none"
)


def validate_recipe(recipe: dict[str, Any], environment: Mapping[str, str]) -> None:
"""Reject metadata mismatches without overwriting recipe-owned server settings."""
role = recipe["roles"]["agg"]
Expand Down Expand Up @@ -96,7 +107,10 @@ def validate_recipe(recipe: dict[str, Any], environment: Mapping[str, str]) -> N
"benchmark type": (benchmark["type"], "custom"),
"benchmark MODEL": (workload["MODEL"], environment["MODEL"]),
"SPEC_DECODING": (speculation, environment["SPEC_DECODING"]),
"USE_CHAT_TEMPLATE": (workload["USE_CHAT_TEMPLATE"], "true" if spec else "false"),
"USE_CHAT_TEMPLATE": (
workload["USE_CHAT_TEMPLATE"],
"true" if spec or _qwen35_b300_fp8(recipe, environment) else "false",
),
}
if "CONC" in workload:
expected["CONC"] = (str(workload["CONC"]), environment["CONC"])
Expand Down Expand Up @@ -168,6 +182,17 @@ def runtime_arguments(config: str, environment: Mapping[str, str]) -> list[str]:
}[environment["FRAMEWORK"]]
for key in context_keys:
overrides += ["--set", f"roles.agg.args.{key}={context}"]
if _qwen35_b300_fp8(recipe, environment) and environment["CONC"] == "256":
overrides += [
"--set",
"roles.agg.args.log-requests=true",
"--set",
"roles.agg.args.log-requests-level=3",
"--set",
'roles.agg.args.log-requests-format="json"',
"--set",
'roles.agg.env.SGLANG_LOG_REQUEST_EXCEEDED_MS="0"',
]
return [*overrides, "--set", 'benchmark.env.RESULT_DIR="/logs"']


Expand Down
42 changes: 42 additions & 0 deletions perf-changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8950,3 +8950,45 @@
description:
- "Update SGLang image from v0.5.19-cu130 to v0.5.20-cu130 and pass --cuda-graph-max-bs-decode after the alias removal."
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/3334

- config-keys:
- qwen3.5-fp8-b300-sglang
scenario-type:
- fixed-seq-len
description:
- Preserve Qwen3.5 FP8 b300 coverage and require validated power; include the article
ladder where missing.
- 保留现有覆盖并要求通过验证的功耗,补齐缺失的文章并发梯度。
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/3379

- config-keys:
- qwen3.5-fp8-b300-sglang
scenario-type:
- fixed-seq-len
description:
- Route Qwen3.5 FP8 STP through the existing B300 batch allocation path, retaining
its serving settings and measurements; the batch container step uses PMIx.
- 将 Qwen3.5 FP8 STP 接入现有 B300 batch 分配路径,保留服务参数和测量设置;batch 容器步骤使用 PMIx。
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/3379

- config-keys:
- qwen3.5-fp8-b300-sglang
scenario-type:
- fixed-seq-len
description:
- Disable JIT DeepGEMM for Qwen3.5 FP8 B300 to validate the native Blackwell
scale-format accuracy warning with the existing FlashInfer fallback.
- 在 Qwen3.5 FP8 B300 上关闭 JIT DeepGEMM,以现有 FlashInfer 回退路径验证 Blackwell
scale-format 精度警告;保留模型、评测输入与准确率门槛。
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/3379

- config-keys:
- qwen3.5-fp8-b300-sglang
scenario-type:
- fixed-seq-len
description:
- Preserve the validated DeepGEMM-off Qwen B300 recipe, chat-template workload,
PMIx launch and c1-c256 power coverage through the native SRT launcher.
- 在原生 SRT 启动路径中保留 Qwen B300 关闭 DeepGEMM 的配方、聊天模板、
PMIx 和 c1-c256 功耗覆盖。
pr-link: https://github.com/SemiAnalysisAI/InferenceX/pull/3379
54 changes: 54 additions & 0 deletions utils/test_srt_single_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,3 +453,57 @@ def test_b300_keeps_agentic_and_explicit_collector_dispatch(tmp_path, collector)
assert calls[-1][-2:] == ["bash", expected]
assert "--jobid=42" in calls[-1]
assert (tmp_path / "cancelled").read_text() == "42\n"


@pytest.mark.parametrize("eval_only,conc,capture", [
("false", "256", False), ("true", "128", False), ("true", "256", True),
])
def test_qwen_b300_keeps_chat_template_and_eval_capture(point, eval_only, conc, capture):
path, recipe, env = point
model = "Qwen/Qwen3.5-397B-A17B-FP8"
recipe["model"]["path"] = f"hf:{model}"
recipe["resources"]["gpu_type"] = "b300"
recipe["benchmark"]["env"].update(MODEL=model, USE_CHAT_TEMPLATE="true")
path.write_text(yaml.safe_dump({"base": recipe}))
env = {**env, "MODEL": model, "CONC": conc, "EVAL_ONLY": eval_only,
"MAX_MODEL_LEN": "9472"}
argv = runtime_arguments(f"{path}:base", env)
actual = copy.deepcopy(recipe)
apply_overrides_to_recipe(actual, parse_overrides(argv[1::2], []))
assert actual["benchmark"]["env"]["USE_CHAT_TEMPLATE"] == "true"
args = actual["roles"]["agg"]["args"]
assert args.get("log-requests", False) is capture
if capture:
assert args["log-requests-level"] == 3
assert args["log-requests-format"] == "json"
assert actual["roles"]["agg"]["env"]["SGLANG_LOG_REQUEST_EXCEEDED_MS"] == "0"
assert args["context-length"] == 9472
else:
assert "SGLANG_LOG_REQUEST_EXCEEDED_MS" not in actual["roles"]["agg"].get("env", {})
recipe["benchmark"]["env"]["USE_CHAT_TEMPLATE"] = "false"
path.write_text(yaml.safe_dump({"base": recipe}))
with pytest.raises(ValueError, match="USE_CHAT_TEMPLATE"):
runtime_arguments(f"{path}:base", env)


@pytest.mark.parametrize("change", ["hardware", "model", "precision"])
def test_qwen_chat_template_exception_does_not_change_neighbor_profiles(point, change):
path, recipe, env = point
model = "Qwen/Qwen3.5-397B-A17B-FP8"
recipe["model"]["path"] = f"hf:{model}"
recipe["resources"]["gpu_type"] = "b300"
recipe["benchmark"]["env"]["MODEL"] = model
env = {**env, "MODEL": model, "CONC": "256", "EVAL_ONLY": "true", "MAX_MODEL_LEN": "9472"}
if change == "hardware":
recipe["resources"]["gpu_type"] = "b200"
elif change == "model":
recipe["model"]["path"] = "hf:test/other"
recipe["benchmark"]["env"]["MODEL"] = env["MODEL"] = "test/other"
else:
recipe["model"]["precision"] = env["PRECISION"] = "fp4"
path.write_text(yaml.safe_dump({"base": recipe}))
argv = runtime_arguments(f"{path}:base", env)
actual = copy.deepcopy(recipe)
apply_overrides_to_recipe(actual, parse_overrides(argv[1::2], []))
assert actual["benchmark"]["env"]["USE_CHAT_TEMPLATE"] == "false"
assert "log-requests" not in actual["roles"]["agg"]["args"]
Loading