Prhub

#42666 [CPU Backend] Improve cpu thread utilization

原始 PR 作者 tianmu-li 合并时间 2026-05-18 18:04 文件变更 2 提交数 5 评论 0 代码增减 +4 / -6

执行摘要

优化 CPU 后端线程利用率

CPU 后端在线程数非 2 的幂(如 31)时,原有 Attention 任务分配存在不均衡,且 KMP_BLOCKTIME=1 导致线程过早休眠,影响利用率。PR body 明确说明目的是“reduce attention work per thread to allow better utilization of arbitrary number of threads”以及“tune KMP-related env variables”。

推荐合并。这是一个精准且经过基准验证的性能优化,改动量小(+4/-6),风险极低。对于 vLLM CPU 用户,建议关注此 PR 后的性能变化。

讨论亮点

该 PR 未产生人工 review 评论。gemini-code-assist[bot] 自动总结了变更内容,无进一步讨论。bigPYJ1151 审核通过并表示“Verified the tuning and it is effective.”

实现拆解

  1. 修正 Attention 任务分配粒度:在 csrc/cpu/cpu_attn_impl.hppAttentionScheduler 中,移除 kv_len_per_thread 计算公式末尾的 * (use_gqa ? input.num_heads_kv : input.num_heads_q) 乘数。该乘数导致每个线程分配的 KV 长度被放大 num_heads 倍,使线程间的任务量差异变大;移除后每个线程处理更统一的 KV 片,提升任意线程数下的负载均衡。

  2. 调整 OpenMP 线程环境变量:在 vllm/utils/ompmultiprocessing.pyconfigure_omp_envs 方法中:

    • KMP_BLOCKTIME"1" 改为 "5",延后线程进入休眠的时间,减少频繁唤醒开销,避免线程利用率不足。
    • 删除 KMP_FORKJOIN_BARRIER_PATTERNKMP_PLAIN_BARRIER_PATTERNKMP_REDUCTION_BARRIER_PATTERN 三个环境变量设置(均设为 "dist,dist")。这是因为这些屏障模式仅在跨 NUMA 节点时有意义,而 vLLM 推荐且默认场景下线程绑定在单个 NUMA 节点内,设置此模式会引入不必要的开销。
文件 模块 状态 重要度
vllm/utils/ompmultiprocessing.py 线程管理 modified 5.5
csrc/cpu/cpu_attn_impl.hpp Attention 调度器 modified 4.72

关键源码片段

vllm/utils/ompmultiprocessing.py core-logic

调整 KMP_BLOCKTIME 从 1 到 5,并移除三个 BARRIER_PATTERN 环境变量,直接影响 OpenMP 线程调度行为。

# 文件 : vllm/utils/ompmultiprocessing.py
# 在 configure_omp_envs 方法中,IOMP 环境变量设置部分(use_iomp 分支)if self.use_iomp:
    # 设置 IOMP 环境变量
    cpu_list_str = ",".join(cpu_list)
    envs_dict["KMP_AFFINITY"] = (
        f"granularity=fine,explicit,proclist=[{cpu_list_str}]"
    )
    # 线程在执行完并行区域后等待的时间(毫秒),
    # 值设为 5 可以掩盖线程利用不足的问题,
    # 调试线程利用问题时可以设回 1。
    envs_dict["KMP_BLOCKTIME"] = "5" # 从 "1" 改为 "5"
    # 防止 CPU 进入低性能状态
    envs_dict["KMP_TPAUSE"] = "0"
    # 移除以下三行:
    # envs_dict["KMP_FORKJOIN_BARRIER_PATTERN"] = "dist,dist"
    # envs_dict["KMP_PLAIN_BARRIER_PATTERN"] = "dist,dist"
    # envs_dict["KMP_REDUCTION_BARRIER_PATTERN"] = "dist,dist"
csrc/cpu/cpu_attn_impl.hpp core-logic

修复 kv_len_per_thread 计算,移除 head 数量乘数,使线程任务分配更均衡。

// 文件 : csrc/cpu/cpu_attn_impl.hpp
// 在 AttentionScheduler 的调度函数中,计算每个线程应处理的 KV 长度const int64_t kv_len_per_thread =
    (((total_kv_len / thread_num) + kv_len_alignment - 1) /
     kv_len_alignment) *
    kv_len_alignment;
    // 移除原先的 : * (use_gqa ? input.num_heads_kv : input.num_heads_q);
    // 该乘数放大了每个线程的工作量,导致线程间负载不均。
    // 修正后,每个线程直接处理对齐后的 KV token 长度,
    // 与任意线程数(如 31)都能更好地匹配。

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  1. 回归风险:移除 kv_len_per_thread 中的 head 乘数,可能影响 GQA(Grouped Query Attention)场景下线程的工作量计算,但测试表明吞吐量提升且功能正确。
  2. 性能波动:KMP_BLOCKTIME 从 1 改为 5 对短 prompt 场景(如 ISL=128, OSL=128)可能提升不明显(+7%),但对长输出场景(ISL=128, OSL=2048)提升显著(+17%)。极短请求场景无退化。
  3. 移除 barrier 模式:对于确实跨 NUMA 节点运行的用户,移除 BARRIER_PATTERN 可能导致性能下降,但 vLLM 默认推荐单 NUMA 绑定,风险可控。

影响范围:仅影响 CPU 后端推理路径。对 Intel CPU 用户,尤其是使用 OpenMP 并绑定线程到单个 NUMA 节点的场景,吞吐量提升 7%~17%。变更向后兼容,无需用户显式修改配置。测试覆盖:未直接修改测试文件,但作者提供了吞吐量基准对比数据。

性能调优影响面窄 缺少测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论