Prhub

#28308 [Intel GPU] add pytorch profiling support for XPU in bench offline throughput and enhance num steps

原始 PR 作者 polisettyvarma 合并时间 2026-06-29 09:10 文件变更 1 提交数 1 评论 14 代码增减 +35 / -4

执行摘要

XPU profiling 支持与步数增强

需要在 Intel GPU(XPU)上对 offline_throughput 基准测试进行 profiling,以分析推理性能瓶颈。现有 profiling 仅支持 GPU/CUDA,且无法控制 profiling 的步数,导致 trace 文件过大或包含不关心的阶段。

值得精读。该 PR 展示了如何为 benchmark 工具统一添加硬件 profiling 支持,设计简洁,可扩展性强。关注点在于 start_profile 接口的设计是否兼容所有 backend。

讨论亮点

Reviewer yanbing-j 指出初始实现中 --profile-start-step 的默认值 output_len // 2 无效,且默认只 profiling 一步也不合理。随后又发现当设置 profile_steps 时,原来的 stop_profile()monitor_trace_file 被遗漏。作者 polisettyvarma 回应称当 profile_steps 传入时 backend 自行处理停止,并已补充 monitor_trace_file。最终 reviewer 同意移除 --profile-start-step 参数,仅保留 --profile-steps

实现拆解

  1. BenchArgs 类中新增字段:在 python/sglang/benchmark/offline_throughput.pyBenchArgs 数据类中添加 profile_activities: Tuple[str](默认 ("CPU", "GPU"))和 profile_steps: Optional[int](默认 None),用于存储用户指定的 profiling 配置。
  2. 添加 CLI 参数解析:在 add_cli_args 静态方法中增加 --profile-activities(支持 CPU、GPU、CUDA_PROFILER、XPU 多选)和 --profile-steps(int 类型)参数,并更新帮助文档中的使用示例。
  3. 修改 profiling 调用逻辑:在 throughput_test_once 函数中,将原有的 backend.start_profile() 改为带参数调用 backend.start_profile(num_steps=profile_steps, activities=profile_activities),并调整 stop_profile 的逻辑:当指定 profile_steps 时,profiler 由 backend 内部自动停止,无需显式调用 stop_profile;同时修复了 trace 文件监控逻辑,确保 monitor_trace_file 被正确调用。
  4. 传递参数链路:在 throughput_test 函数中将 bench_args 中的 profile_activitiesprofile_steps 传递给 throughput_test_once
文件 模块 状态 重要度
python/sglang/benchmark/offline_throughput.py 基准测试 modified 6.78

关键符号

throughput_test_once throughput_test BenchArgs.add_cli_args

关键源码片段

python/sglang/benchmark/offline_throughput.py core-logic

唯一修改的文件,新增 profiling 参数和调用逻辑,核心变更所在。

以下代码展示了 BenchArgs 中的新增字段、CLI 参数注册以及 throughput_test_once 中修改后的 profiling 调用逻辑。

# 文件 : python/sglang/benchmark/offline_throughput.py@dataclasses.dataclass
class BenchArgs:
    # ... 其他字段不变 ...
    profile: bool = False
    # 新增:profiling 活动类型,默认 CPU+GPU,支持 XPU
    profile_activities: Tuple[str] = ("CPU", "GPU")
    # 新增:profiling 步数,None 表示对整个 generate 过程进行 profiling
    profile_steps: Optional[int] = None
    skip_warmup: bool = False
    do_not_exit: bool = False
    prompt_suffix: str = ""
    return_logprob: bool = False
    logprob_start_len: int = -1
​
    @staticmethod
    def add_cli_args(parser: argparse.ArgumentParser):
        # ... 其他参数 ...
        parser.add_argument(
            "--profile",
            action="store_true",
            help="Use Torch Profiler. The endpoint must be launched with "
            "SGLANG_TORCH_PROFILER_DIR to enable profiler.",
        )
        # 新增:--profile-activities 参数,可指定多个活动(如 CPU GPU XPU)
        parser.add_argument(
            "--profile-activities",
            type=str,
            nargs="+",
            default=["CPU", "GPU"],
            choices=["CPU", "GPU", "CUDA_PROFILER", "XPU"],
            help="Profiler activities: CPU, GPU, XPU, CUDA_PROFILER. "
            "If CPU/GPU/XPU, use torch profiler. If CUDA_PROFILER, use CUDA profiler.",
        )
        # 新增:--profile-steps 参数,限制 profiling 的步数
        parser.add_argument(
            "--profile-steps",
            type=int,
            default=None,
            help="Number of steps to profile. If not specified, profiles all steps.",
        )
​
​
def throughput_test_once(
    ignore_eos: bool,
    extra_request_body: Dict,
    profile: bool,
    profile_activities=None, # 新增参数
    profile_steps=None, # 新增参数
    return_logprob: bool = False,
    logprob_start_len: int = -1,
):
    # ...
    if profile:
        assert "SGLANG_TORCH_PROFILER_DIR" in os.environ, \
            "Please set SGLANG_TORCH_PROFILER_DIR."
        os.makedirs(os.environ["SGLANG_TORCH_PROFILER_DIR"], exist_ok=True)
        known_files = None
        # 传入 num_steps 和 activities 以支持受限 profiling
        backend.start_profile(
            num_steps=profile_steps,
            activities=profile_activities,
        )
        if profile_steps:
            # 当指定步数时,预先记录已存在的文件,以便后续只提取新生成的文件
            dir = os.getenv("SGLANG_TORCH_PROFILER_DIR")
            known_files = set(os.listdir(dir))
​
    st = time.perf_counter()
    gen_out = backend.generate(
        # ...
    )
    # ...
    if profile:
        dir = os.getenv("SGLANG_TORCH_PROFILER_DIR")
        if not profile_steps:
            # 未指定步数时,需要手动停止 profiler 并记录文件
            known_files = set(os.listdir(dir))
            backend.stop_profile()
        # 监控新生成的 trace 文件并打印
        monitor_trace_file(known_files, dir)

评论区精华

--profile-start-step 参数的必要性 设计

Reviewer 提出 `--profile-start-step` 的默认值无效,且 start_step 仅对 decode 阶段有效,不符合用户预期。作者解释其主要用于 decode 阶段 profiling,而 prefill 数据也重要,因此 reviewer 建议删除该参数。

结论:移除了 `--profile-start-step` 参数,仅保留 `--profile-steps`,并在文档中说明 `profile_steps` 用于控制 decode 步数。 · 已解决

profile 生命周期管理:stop_profile 缺失 正确性

Reviewer 指出当设置 `profile_steps` 时,`stop_profile()` 和 `monitor_trace_file` 调用缺失,可能导致 profiling 无法正确停止或 trace 文件无法监控。

结论:作者解释当 `profile_steps` 传参时,backend 内部自动停止 profiler,但仍需调用 `monitor_trace_file`。修复后将 `monitor_trace_file` 移到条件之外,确保无论是否指定步数都会执行。 · 已解决

风险与影响

低风险。变更局限于基准测试脚本,不影响模型推理核心逻辑。但需注意:start_profilenum_stepsactivities 参数的实现依赖于底层 backend(Runtime/Engine),若 backend 不支持这些参数可能导致运行时错误,但当前修改假设 backend 已支持或具有容错处理。

用户:XPU 用户现在可以使用 --profile-activities XPU 进行 profiling,并通过 --profile-steps N 控制 profiling 步数,减少 trace 文件大小。系统:无影响。团队:为后续扩展其他硬件平台的 profiling 提供了可复用的参数模式。

对外部 backend 接口的隐式依赖 单文件变更,无测试覆盖

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论