背景

  • 基于MindIE推理引擎,使用昇腾NPU
  • 使用PD混合部署方式
  • 目标是调测服务化的极致性能

服务化性能调优流程

image

服务化调优实践

性能指标计算逻辑

1755590571783_image

  • 纯模型:
    non_first_token_throughput = batch_size / non_first_token_time
    e2e_throughput = batch_size * seq_len_out / e2e_time

  • 服务化
    OutputGenerateSpeed = round(sum(result.generate_tokens_len) / infer_time, 4)
    InputGenerateSpeed = round(sum(result.input_tokens_len) / infer_time, 4)
    TotalGenerateSpeed = round(sum(result.input_tokens_len + result.generate_tokens_len) / infer_time, 4)

测试环境/场景

驱动、固件 MindIE 模型 输入/输出 数据量 场景 服务器
25.0.rc1 2.1.RC1 Qwen2.5-7B-Instruct 256/256 500条 单卡最大吞吐 800I A2(32GB)

benchmark测试数据脚本synthetic_config.json:

{
    "Input":{
        "Method": "uniform",
        "Params": {"MinValue": 256, "MaxValue": 256}
    },
    "Output": {
        "Method": "gaussian",
        "Params": {"Mean": 100, "Var": 200, "MinValue": 256, "MaxValue": 256}
    },
    "RequestCount": 500
}

前置准备

# 初始化环境变量
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
source /usr/local/Ascend/mindie/set_env.sh
source /usr/local/Ascend/atb-models/set_env.sh
export MINDIE_LOG_TO_STDOUT=1

# 拉起服务
/usr/local/Ascend/mindie/latest/mindie-service/bin/mindieservice_daemon

1755516095405_image

  • 基于初始环境、默认服务化配置,跑个基本性能
    执行命令如下:
benchmark \
--DatasetType "synthetic" \
--ModelName qwen \
--ModelPath "/models/Qwen2.5-7B-Instruct/" \
--TestType vllm_client \
--Http http://127.0.0.1:1025 \
--ManagementHttp http://127.0.0.2:1026 \
--Concurrency 100 \
--MaxOutputLen 256 \
--TaskKind stream \
--Tokenizer True \
--SyntheticConfigPath ./synthetic_config.json

1755516466646_image

环境预检

msprechecker工具使用

工具使用说明

1754990106721_image

执行预检:

pip install msprechecker

# 默认进行环境变量、系统配置的校验
msprechecker precheck

1755516557483_image

环境变量说明

基线变量:

# 先使能各组件的默认环境变量
source /usr/local/Ascend/mindie/set_env.sh
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
source /usr/local/Ascend/atb-models/set_env.sh

# atb-models环境变量
export ATB_LLM_HCCL_ENABLE=1
export ATB_WORKSPACE_MEM_ALLOC_ALG_TYPE=3 
export ATB_LAYER_INTERNAL_TENSOR_REUSE=1
export ATB_OPERATION_EXECUTE_ASYNC=1 # 默认开启
export ATB_CONVERT_NCHW_TO_ND=1
export ATB_WORKSPACE_MEM_ALLOC_GLOBAL=1
export ATB_CONTEXT_WORKSPACE_SIZE=0
export ATB_LAUNCH_KERNEL_WITH_TILING=1
export ATB_LLM_ENABLE_AUTO_TRANSPOSE=0

# CANN
unset ASCEND_LAUNCH_BLOCKING
export HCCL_DETERMINISTIC=false
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_CONNECT_TIMEOUT=7200
export HCCL_EXEC_TIMEOUT=0
export HCCL_RDMA_PCIE_DIRECT_POST_NOSTRICT=TRUE

# Ascend Extension for Pytorch
export INF_NAN_MODE_ENABLE=1
export TASK_QUEUE_ENABLE=2
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

# MindIE Service
# 异步发射,几乎所有情况下推荐开启
export MINDIE_ASYNC_SCHEDULING_ENABLE=1

非基线变量:

# host侧性能相关
export OMP_NUM_THREADS=10: 建议设置8-16之间的值,利用Numpy的OpenMP多线程能力,加速host侧前后处理

# 内存相关
export=NPU_MEMORY_FRACTION=0.96: 0-1之间,推荐0.96/0.97,比例越高吞吐越高,遇到oom报错或服务化无响应卡死调小至0.9左右

# 通信相关
export HCCL_BUFFSIZE=1024:一般使用默认推荐值即可,多机配置需相同,通信数据量大的场景下可适当调大,如通信域占用显存过多出现显存瓶颈可适当调小

# 日志相关(关闭所有日志,开箱不建议这么使用)
for var in $(compgen -e | grep 'STDOUT$'); do
  export "$var=0"
done

for var in $(compgen -e | grep 'LOG_TO_FILE$'); do
  export "$var=0"
done


# 系统和硬件相关
# CPU高性能模式:可使用cpupower frequency-set -g performance设置,cpupower freqeuncy-info查询

# 大页内存:通过cat /sys/kernel/mm/transparent\_hugepage/enabled检查

# 绑核:CPU瓶颈时,建议使用将mindie绑核至奇数NUMA节点,避免服务化框架和算子下发等host侧任务竞争CPU资源
lscpu  # 查看CPU规格
# 168-191要根据实际情况修改
taskset -c 168-191 ./bin/mindieservice_daemon

服务化性能测试

  • 尝试1:
export MINDIE_ASYNC_SCHEDULING_ENABLE=1
export OMP_NUM_THREADS=10

# 跑benchmark测试:

1755517012174_image

性能提升:(2024 - 1725) / 1725 = 17.33%

  • 尝试2:基于尝试1的基础上,增加奇节点绑核
lscpu

taskset -c 32-63 /usr/local/Ascend/mindie/latest/mindie-service/bin/mindieservice_daemon

# 跑benchmark测试:

1755517406768_image

性能提升:(2005 - 1725) / 1725 = 16.23%

可以看到绑核反而让性能变差了,所以绑核不是必须的,要依具体场景而设置,后续有相关案例会补充。

摸测纯模型最大吞吐&最大batchsize(可选)

## 单机场景
bash run.sh pa_[data_type] performance_maxbs [case_pair] [batch_range] [time_limit] [model_name] ([is_chat_model]) [weight_dir] ([trust_remote_code]) [chip_num] ([max_position_embedding/max_sequence_length])

说明:
1. case_pair接收一组或多组输入,格式为[[seq_in_1,seq_out_1],...,[seq_in_n,seq_out_n]], 中间不接受空格,如[[256,256],[512,512]]
2. batch_range接收一组或多组输入,数量与case_pair的组数一致,表达对应的case_pair会在给定的batch_range中寻找摸测满足time_limit的最大batch_size.
格式为[[lb1,rb1],...,[lbn,rbn]],其中区间均为闭区间。如[[1,1000],[200,300]]
3. time_limit:摸测最大bs时的非首token时延最大值。
4. 结果保存: [...]/tests/modeltest/result/模型名/ 下,
    1. 以"_round_result.csv"结尾的文件内保存了过程数据
    2. 以"_final_result.csv"结尾的文件内保存了最终数据, 会呈现在控制台末尾


# 如何计算batch_range:待补充??

# 样例
cd /usr/local/Ascend/atb-models/tests/modeltest
bash run.sh pa_bf16 performance_maxbs [[256,256]] [[200,300]] 1000 qwen /models/Qwen2.5-7B-Instruct/ 1
# 如设置batchsize过大,需要调整batch_range

1755518818114_image

使用服务化专家建议工具

msserviceprofiler工具使用

工具使用说明

执行命令:

# 工具安装
pip install -U msserviceprofiler

# 指定输入输出的 token 长度 `-in, --input_token_num` 以及 `-out, --output_token_num`
msserviceprofiler advisor -in 256 -out 256

# 或提供 `instance` 文件夹
msserviceprofiler advisor -i ${path}/instance/

1755519050971_image

服务化性能测试

  • 尝试1:参考建议,把maxBatchSize改为438

1755519448759_image

测试性能比默认还要差??分析可能是客户端并发设置太小了(当前设置100)

  • 尝试2:基于尝试1,增加客户端并发量,由100->250
# benchmark命令
benchmark \
--DatasetType "synthetic" \
--ModelName qwen \
--ModelPath "/models/Qwen2.5-7B-Instruct/" \
--TestType vllm_client \
--Http http://127.0.0.1:1025 \
--ManagementHttp http://127.0.0.2:1026 \
--Concurrency 250 \
--MaxOutputLen 256 \
--TaskKind stream \
--Tokenizer True \
--SyntheticConfigPath ./synthetic_config.json

1755519677864_image

性能提升:(2306 - 1725) / 1725 = 33.68%

  • 尝试3:继续增大maxBatchSize和客户端并发量
maxBatchSize: 438->600  #当前测试数据量只有500条,batchsize设置超过500没什么作用。
Concurrency:  250->500

1755519999490_image

性能提升:(2306 - 1725) / 1725 = 18.20%

  • 尝试4:基于尝试3开启异步和多线程处理
export MINDIE_ASYNC_SCHEDULING_ENABLE=1
export OMP_NUM_THREADS=10

1755520265289_image

性能提升:(2655 - 1725) / 1725 = 53.91%

  • 更多尝试
    1.可以尝试调整prefill阶段的批次;2.可以调整调度策略;3.可以调整客户端的请求并发量和请求频率;
    以上内容可以参考官方文档指导:服务化性能调优流程

  • 总结:纯模型测试性能为3624 TPS,服务化最大为2655 TPS,服务化是纯模型的0.73倍。需要采集服务化性能进一步分析,详见下文。

服务化性能采集&分析

profiling采集指导

性能采集&解析

# 数据采集
# 1准备采集配置文件ms_service_profiler_config.json
# 参数说明详见上面指导链接
{
    "enable": 1,
    "prof_dir": "${PATH}",
    "profiler_level": "INFO",
    "host_system_usage_freq": -1,
    "npu_memory_usage_freq": -1,
    "acl_task_time": 0,
    "acl_prof_task_time_level": "L0",
    "timelimit": 0
}
# 2 执行采集(在服务化端session设置)
export SERVICE_PROF_CONFIG_PATH="${PATH}/ms_service_profiler_config.json"

# 拉起服务化,跑性能测试

# 数据解析
python3 -m ms_service_profiler.parse --input-path=${PATH}/prof_dir/

# 数据可视化 

性能数据采集如下:

1755566650234_image

数据解析后生成的内容:(在命令执行路径下的output目录)

1755567945376_image

性能分析

性能问题可分为三大类:下发(调度)、计算、通信

性能数据可视化&分析指导

  • 总览图

1755570802593_image

  • 问题1:推理过程中,free时间占比为16%,判断host下发存在瓶颈

1755586084299_image

  • 问题2:分析batch.csv,发现prefill的batch最大为32,decode batch最大为371
    prefill batch被maxPrefillTokens给限制了。

服务化性能测试

# 在服务端设置
# 当前环境TASK_QUEUE_ENABLE=1
export TASK_QUEUE_ENABLE=2

# benchmark测试如下:

1755588511687_image

由于是基于上面优化基础上,叠加优化,所以要和上面最好的一次性能做比较,即2655.
性能提升:(2662 - 2655) / 2655 = 0.26%

  • 问题2:优化prefill
maxPrefillTokens: 由8192->12800.  (输入平均是256, prefill batchsize是50)

叠加上面所有优化,跑benchmark测试:

1755589427875_image

性能提升:(2673 - 2662) / 2662 = 0.41%

  • 总结:整体性能调优提升了(2673 - 1725) / 1725 = 55%,服务化是纯模型的0.74倍

自动寻优

整体概述

参考指导:链接

基本功能: 通过服务化自动寻优工具,自动生成服务化参数组合(包括服务化和客户端),尽可能逼近最优解;开发者可以基于推荐的参数组合进行微调,进一步优化。

两种模式:

  • 轻量化模式 : 注重精度和可靠性,结合参数验证、参数寻优模块,通过真机实测给出可靠的服务化参数推荐值。
  • 仿真模式 : 注重速度及资源占用,调动所有模块快速、精确地预测各组参数的吞吐,在较低NPU资源占用的前提下给出服务化参数推荐值。

快速上手(轻量化模式)

前置条件

用户需要提前确认服务化(如MindIE Service/VLLM Server)、压测工具(如benchmark/vllm_benchmark/aisbench)可以正常运行。这里包括环境变量的设置、服务化配置文件的修改等要先完成。

自动寻优工具的安装
# 如果使用轻量化的方式进行寻优则只需安装最少的依赖即可
git clone https://gitcode.com/Ascend/msit.git
cd msit/msserviceprofiler
pip install -e .[real] 

# 仿真模式需安装相关加速包
pip install -e .[speed]  
# 如果上述安装失败,可尝试安装较少依赖的三方包,但训练模型时,大数据量时性能较低。
pip install -e .[train] 

export PYTHONPATH=$PWD:$PYTHONPATH
配置修改

具体修改内容详见链接

配置文件路径:msit/msserviceprofiler/msserviceprofiler/modelevalstate/config.toml

  • 寻优参数:
    n_particles (寻优种子数)、iters (迭代轮次数)、 tpot_slo (time_per_output_token的限制时延)等。 用户可根据预估时间来自行配置种子和迭代次数。我们单个种子使用时间为拉起服务+测试数据。比如用户拉起服务+完成测试需9-10min,且愿意用8小时来进行寻优,则一共可跑约50个种子,建议用户配置5 * 10。设置种子数为10,迭代次数为5,建议用户配置种子数为迭代次数的2倍左右。
    配置说明:

    参数 说明 建议值
    n_particles 寻优种子数,即一组生成的参数组合数 建议设为 15 ~ 30,范围为1-1000
    iters 迭代轮次数 建议设为 5 ~ 10,范围为1-1000
    ttft_penalty time_to_first_token 即首token时延超时惩罚系数,若对 time_to_first_token 没有时延要求设置为0即可 按需开启设为1
    tpot_penalty time_per_output_token 即非首token时延超时惩罚系数,若对time_per_output_token没有时延要求设置为0即可 按需开启设为1
    success_rate_penalty 请求成功率惩罚系数,默认值为5 建议设为5
    ttft_slo time_to_first_token的限制时延 单位s,如对time_to_first_token限制为2s内,则设为2
    tpot_slo time_per_output_token的限制时延 单位s,如对time_per_output_token限制为50ms内,则设为0.05
    service 标注多机启动时为主机或从机 多机场景下从机设为 slave
    sample_size 对原始数据集采样大小,用采样后的数据进行调优,可增加寻优效率 建议设为原数据集请求的1 / 3, 要求不小于1000
  • 测评工具参数(参考上面链接)

  • 服务化参数(参考上面链接)

日志配置
export MODELEVALSTATE_LEVEL=INFO
启动寻优
msserviceprofiler optimizer -e mindie -b ais_bench

# 注意,启动寻优命令不需要先拉起服务化,寻优工具会自动拉起。

image11

输出结果说明

可以使用export MODEL_EVAL_STATE_CUSTOM_OUTPUT来设置输出路径。 输出件为csv,若不指定输出路径则在modelevalstate/result/store下存放。 输出csv中的每一行对应一组参数,前四列为性能指标。用户可以根据需求筛选满足要求的性能行,将MindIE参数以及benchmark的参数改为csv中的数据即可。

image22

调优案例

自动寻优案例

环境信息:

驱动、固件 MindIE 模型 输出长度 数据集 场景 服务器
25.2.0 2.1.RC1 DeepSeek-R1-Distill-Qwen-7B 512 gsm8k(1319条) 单卡最大吞吐 800T A2(64GB)

默认配置吞吐:

# 服务化启动
/usr/local/Ascend/mindie/latest/mindie-service/bin/mindieservice_daemon

# ais_bench执行命令
/usr/local/bin/ais_bench --models vllm_api_stream_chat --datasets gsm8k_gen_0_shot_cot_str_perf --mode perf --num-prompts 1319 --work-dir /root/result/ais_bench --debug

image33

自动寻优生成参数组合及吞吐:

  • 前置准备:参考自动寻优->快速上手完成寻优动作;
  • 根据自动寻优生成的data_storage_*.csv文件,找到最高吞吐的参数组合,如下(绿色为寻优生成的参数):

image44

  • 基于最优参数,执行测试
# 服务化启动
/usr/local/Ascend/mindie/latest/mindie-service/bin/mindieservice_daemon

# ais_bench执行命令
/usr/local/bin/ais_bench --models vllm_api_stream_chat --datasets gsm8k_gen_0_shot_cot_str_perf --mode perf --num-prompts 1319 --work-dir /root/result/ais_bench --debug

image55

寻优前后性能提升:
整体性能调优提升了(3612 - 3103) / 3103 = 16.4%

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐