语言模型推理性能测试
benchmark方法介绍
性能benchmark包括两部分。
- 静态性能测试:评估在固定输入、固定输出和固定并发下,模型的吞吐与首token延迟。该方式实现简单,能比较清楚的看出模型的性能和输入输出长度、以及并发的关系。
- 动态性能测试:评估在请求并发在一定范围内波动,且输入输出长度也在一定范围内变化时,模型的延迟和吞吐。该场景能模拟实际业务下动态的发送不同长度请求,能评估推理框架在实际业务中能支持的并发数。
性能benchmark验证使用到的脚本存放在代码包AscendCloud-LLM-xxx.zip的llm_tools/llm_evaluation目录下。
benchmark_tools |--- modal_benchmark |--- modal_benchmark_parallel.py # modal 评测静态性能脚本 |--- utils.py ├── benchmark_parallel.py # 评测静态性能脚本 ├── benchmark_serving.py # 评测动态性能脚本 ├── generate_dataset.py # 生成自定义数据集的脚本 ├── benchmark_utils.py # 工具函数集 ├── benchmark.py # 执行静态、动态性能评测脚本 ├── requirements.txt # 第三方依赖
目前性能测试已经支持投机推理能力。
静态benchmark验证
本章节介绍如何进行静态benchmark验证。
- 已经上传benchmark验证脚本到推理容器中。如果在步骤四 制作推理镜像步骤中已经上传过AscendCloud-LLM-x.x.x.zip并解压,无需重复执行。
- 进入benchmark_tools目录下,运行静态benchmark验证。
cd benchmark_tools
语言模型脚本相对路径是tools/llm_evaluation/benchmark_tools/benchmark_parallel.py,具体操作命令如下,可以根据参数说明修改参数。python benchmark_parallel.py --backend openai --host ${docker_ip} --port ${port} --tokenizer /path/to/tokenizer --epochs 5 --num-scheduler-steps 8 \ --parallel-num 1 4 8 16 32 --prompt-tokens 1024 2048 --output-tokens 128 256 --benchmark-csv benchmark_parallel.csv
参数说明
- --backend:服务类型,支持tgi、vllm、mindspore、openai等后端。本文档使用的推理接口是openai。
- --host:服务部署的IP,${docker_ip}替换为宿主机实 际的IP地址。
- --port:推理服务端口。
- --tokenizer:tokenizer路径,HuggingFace的权重路径。
- --epochs:测试轮数,默认取值为5。
- --parallel-num:每轮并发数,支持多个,如 1 4 8 16 32。
- --prompt-tokens:输入长度,支持多个,如 128 128 2048 2048,数量需和--output-tokens的数量对应。
- --output-tokens:输出长度,支持多个,如 128 2048 128 2048,数量需和--prompt-tokens的数量对应。
- --benchmark-csv:结果保存文件,如benchmark_parallel.csv。
- --num-scheduler-steps: 需和服务启动时配置的num-scheduler-steps一致。默认为1
- --served-model-name: 选择性添加,在接口中使用的模型名;如果没有配置,则默认为tokenizer。
- --enable-prefix-caching:服务端是否启用enable-prefix-caching特性,默认为false。
- --prefix-caching-num:构造的prompt的公共前缀的序列长度,prefix-caching-num值需小于prompt-tokens。
- --use-spec-decode:是否使用投机推理进行输出统计,不输入默认为false。当使用投机推理时必须开启,否则会导致输出token数量统计不正确。注:由于投机推理的性能测试使用随机输入意义不大,建议开启--dataset-type、--dataset-path,并选择性开启--use-real-dataset-output-tokens使用真实数据集进行测试。
- --dataset-type:当使用投机推理时开启,benchmark使用的数据类型,当前支持random、sharegpt、human-eval三种输入。random表示构造随机token的数据集进行测试;sharegpt表示使用sharegpt数据集进行测试;human-eval数据集表示使用human-eval数据集进行测试。不输入默认为random。注意:当输入为sharegpt或human-eval时,测试数据的输入长度为数据集的真实长度,--prompt-tokens的值会被忽略。
- --dataset-path:数据集的路径,仅当--dataset-type为sharegpt或者human-eval的时候生效。
- --use-real-dataset-output-tokens:当使用投机推理时开启,设置输出长度是否使用数据集的真实长度,不输入默认为false。当使用该选项时,测试数据的输出长度为数据集的真实长度,--output-tokens的值会被忽略。
- --num-speculative-tokens:仅当开启--use-spec-decode时生效,需和服务启动时配置的--num-speculative-tokens一致。默认为-1。当该值大于等于0时,会基于该值计算投机推理的接受率指标。
- 脚本运行完成后,测试结果保存在benchmark_parallel.csv中,示例如下图所示。
图1 静态benchmark测试结果(示意图)
动态benchmark
本章节介绍如何进行动态benchmark验证。
- 获取数据集。动态benchmark需要使用数据集进行测试,可以使用公开数据集,例如Alpaca、ShareGPT。也可以根据业务实际情况,使用generate_datasets.py脚本生成和业务数据分布接近的数据集。
- ShareGPT下载地址: https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json
- Alpaca下载地址: https://github.com/tatsu-lab/stanford_alpaca/blob/main/alpaca_data.json
方法二:使用generate_dataset.py脚本生成数据集方法:
客户通过业务数据,在generate_dataset.py脚本,指定输入输出长度的均值和标准差,生成一定数量的正态分布的数据。具体操作命令如下,可以根据参数说明修改参数。
cd benchmark_tools python generate_dataset.py --dataset custom_datasets.json --tokenizer /path/to/tokenizer \ --min-input 100 --max-input 3600 --avg-input 1800 --std-input 500 \ --min-output 40 --max-output 256 --avg-output 160 --std-output 30 --num-requests 1000
generate_dataset.py脚本执行参数说明如下:
- --dataset:数据集保存路径,如custom_datasets.json。
- --tokenizer:tokenizer路径,可以是HuggingFace的权重路径。backend取值是openai时,tokenizer路径需要和推理服务启动时--model路径保持一致,比如--model /data/nfs/model/llama_7b, --tokenizer也需要为/data/nfs/model/llama_7b,两者要完全一致。
- --min-input:输入tokens最小长度,可以根据实际需求设置。
- --max-input:输入tokens最大长度,可以根据实际需求设置。
- --avg-input:输入tokens长度平均值,可以根据实际需求设置。
- --std-input:输入tokens长度方差,可以根据实际需求设置。
- --min-output:最小输出tokens长度,可以根据实际需求设置。
- --max-output:最大输出tokens长度,可以根据实际需求设置。
- --avg-output:输出tokens长度平均值,可以根据实际需求设置。
- --std-output:输出tokens长度标准差,可以根据实际需求设置。
- --num-requests:输出数据集的数量,可以根据实际需求设置。
- 进入benchmark_tools目录下,切换一个conda环境。
cd benchmark_tools conda activate python-3.9.10
- 执行脚本benchmark_serving.py测试动态benchmark。具体操作命令如下,可以根据参数说明修改参数。
python benchmark_serving.py --backend openai --host ${docker_ip} --port 8080 --dataset custom_datasets.json --dataset-type custom \ --tokenizer /path/to/tokenizer --request-rate 0.01 1 2 4 8 10 20 --num-prompts 10 1000 1000 1000 1000 1000 1000 \ --max-tokens 4096 --max-prompt-tokens 3768 --num-scheduler-steps 8 --benchmark-csv benchmark_serving.csv
- --backend:服务类型,如tgi,vllm,mindspore、openai。
- --host ${docker_ip}:服务部署的IP地址,${docker_ip}替换为宿主机实际的IP地址。
- --port:推理服务端口。
- --dataset:数据集路径。
- --dataset-type:支持三种 "alpaca","sharegpt","custom"。custom为自定义数据集。
- --tokenizer:tokenizer路径,可以是HuggingFace的权重路径,backend取值是openai时,tokenizer路径需要和推理服务启动时--model路径保持一致,比如--model /data/nfs/model/llama_7b, --tokenizer也需要为/data/nfs/model/llama_7b,两者要完全一致。
- --request-rate:请求频率,支持多个,如 0.1 1 2。实际测试时,会根据request-rate为均值的指数分布来发送请求以模拟真实业务场景。
- --num-prompts:某个频率下请求数,支持多个,如 10 100 100,数量需和--request-rate的数量对应。
- --max-tokens:输入+输出限制的最大长度,模型启动参数--max-input-length值需要大于该值。
- --max-prompt-tokens:输入限制的最大长度,推理时最大输入tokens数量,模型启动参数--max-total-tokens值需要大于该值,tokenizer建议带tokenizer.json的FastTokenizer。
- --benchmark-csv:结果保存路径,如benchmark_serving.csv。
- --served-model-name: 选择性添加, 选择性添加,在接口中使用的模型名;如果没有配置,则默认为tokenizer。
- --num-scheduler-steps: 需和服务启动时配置的num-scheduler-steps一致。默认为1
- 脚本运行完后,测试结果保存在benchmark_serving.csv中,示例如下图所示。
图2 动态benchmark测试结果(示意图)
单条请求性能测试
针对openai的/v1/completions以及/v1/chat/completions两个非流式接口,请求体中可以添加可选参数"return_latency",默认为false,若指定该参数为true,则会在相应请求的返回体中返回字段"latency",返回内容如下:
- prefill_latency(首token时延):请求从到达服务开始到生成首token的耗时
- model_prefill_latency(模型计算首token时延):服务从开始计算首token到生成首token的耗时
- avg_decode_latency(平均增量token时延):服务计算增量token的平均耗时
- time_in_queue(请求排队时间):请求从到达服务开始到开始被调度的耗时
- request_latency(请求总时延):请求从到达服务开始到结束的耗时
以上指标单位均是ms,保留2位小数。