2025-04-05 00:59:31 +08:00

145 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LLM API 性能基准测试脚本
## 概述
本 Python 脚本旨在使用 `asyncio``aiohttp` 对 vLLM或兼容 OpenAI API 格式的)服务器进行性能基准测试。它的核心目标是通过解决常见的基准测试陷阱,生成更真实、更稳健的性能评估结果。
该脚本通过测试服务器在不同**输入提示长度**和**并发级别**下的表现,帮助了解服务器在不同负载条件下的扩展性。
## 主要特点
此脚本包含多项特性,以确保基准测试结果更具参考价值:
1. **通过多样化提示避免缓存 (Cache Avoidance):**
* 针对每个测试的输入 Token 长度,脚本会生成一批*独特*的提示。
* 每个提示都包含一个随机的唯一标识符 (`[会话ID: ...]`),并结合了不同的主题句和随机元素。
* 在并发测试期间,尽可能为不同的并发请求分配不同的提示。
* 这显著降低了命中服务器端 KV 缓存优化的可能性,从而更好地衡量原始生成性能,而非缓存读取速度。
2. **控制最小输出长度 (Controlled Output Length):**
* 脚本通过增强提示(例如加入:“请针对上述内容提供详细分析和见解...”)明确指示语言模型生成详细、较长的回复。
* 利用 `max_tokens` 参数,并尝试使用 `min_tokens` 参数(如果 API 端点支持),以鼓励模型产生足够长的输出。
* 这可以防止因模型快速生成极短、无意义回复而导致 `Token/秒` 指标虚高。测试重点在于衡量有意义的生成任务的吞吐量。
3. **可变输入提示长度 (Variable Input Lengths):**
* 基准测试可以配置为在一系列不同的输入提示 Token 长度(例如 `[10, 100, 500, 1000, 2000]`)上运行。
* 测试不同的输入大小至关重要,因为 LLM 的性能(尤其是首个 Token 生成时间和整体吞吐量)会因所提供的上下文大小而显著变化。这避免了仅测试极短提示(例如 < 50 Tokens可能带来的误导性结果
4. **异步并发请求:** 使用 `asyncio` `aiohttp` 高效处理高并发请求
5. **可配置参数:** 通过命令行参数轻松配置 API 端点模型名称API 密钥Token 长度并发级别和输出 Token 限制
6. **详细结果输出:** 以多种格式保存结果
* 原始 CSV (`benchmark_results.csv`)
* 便于比较的透视表 (`benchmark_total_tokens_per_second.csv`, `benchmark_avg_tokens_per_second.csv`)
* 整体 JSON 摘要 (`benchmark_results.json`)
* 用于细粒度分析和调试的单个请求详情 (`requests/` 子目录中的 JSON 文件)
* 测试配置 (`test_config.json`)
* 生成的提示 (`prompts_length_*.txt`)
7. **侧重输出的吞吐量指标:** 主要基于生成的**输出 Tokens** 计算 `tokens_per_second`更清晰地衡量模型的生成速度同时报告了总吞吐量所有并发请求和平均每请求吞吐量
8. **可选性能图表:** 如果安装了 `matplotlib`则生成可视化性能与并发关系的图表
9. **分词器灵活性:** 如果 `tiktoken` 可用则使用它进行精确的 Token 计数否则回退到基于字符的近似计数
## 环境要求
* Python 3.7+
* 所需的 Python 库:
* `aiohttp`
* `pandas`
* `tiktoken` (可选强烈推荐用于精确 Token 计数)
* `matplotlib` (可选用于生成性能图表)
## 安装
克隆仓库或下载脚本文件然后安装必要的库
```bash
pip install aiohttp pandas tiktoken matplotlib
```
或者不安装可选库
```bash
pip install aiohttp pandas
```
## 配置
您可以在脚本顶部直接修改配置参数或者更灵活地通过命令行参数进行配置关键参数包括
* `API_BASE`: 您的 vLLM 或兼容 API 端点的基础 URL (例如 `http://localhost:8000/v1`)。
* `MODEL_NAME`: 部署的模型名称 (例如 `DeepSeek-V3-0324`)。
* `API_KEY`: 您的 API 密钥 (如果服务器需要)。
## 使用方法
在终端中运行脚本 `python your_script_name.py`
**命令行参数:**
* `--token-lengths`: 要测试的输入 Token 长度列表 (例如 `--token-lengths 100 500 1000`)。默认: `[10, 100, 500, 1000, 2000]`
* `--concurrency-levels`: 要测试的并发级别同时请求数列表 (例如 `--concurrency-levels 1 4 8 16`)。默认: `[1, 2, 4, 8, 16, 32]`
* `--max-output-tokens`: 每个请求生成的最大 Token 默认: `500`
* `--min-output-tokens`: 每个请求期望生成的最小 Token 用于提示增强如果 API 支持也作为参数)。默认: `300`
* `--prompts-per-length`: 为每个 Token 长度生成多少个不同的提示默认: `50`
* `--api-base`: 覆盖默认的 API 基础 URL
* `--model`: 覆盖默认的模型名称
* `--api-key`: 覆盖默认的 API 密钥
* `--result-dir`: 指定保存结果的目录 (否则将创建一个带时间戳的目录)。
**示例:**
```bash
python benchmark_vllm.py \
--token-lengths 100 500 1000 2000 \
--concurrency-levels 1 4 8 16 32 64 \
--max-output-tokens 1024 \
--min-output-tokens 500 \
--api-base http://10.10.10.10:8000/v1 \
--model DeepSeek-V3-0324 \
--api-key "your-optional-api-key" \
--result-dir ./my_benchmark_run_1
```
## 输出内容
脚本将创建一个结果目录 `--result-dir` 指定或名为 `benchmark_results_YYYYMMDD_HHMMSS`)。在此目录中您将找到
* `benchmark_results.csv`: 每个输入长度和并发组合的详细结果
* `benchmark_total_tokens_per_second.csv`: 显示总输出 Tokens/ 的透视表
* `benchmark_avg_tokens_per_second.csv`: 显示平均每请求输出 Tokens/ 的透视表
* `benchmark_results.json`: JSON 格式的所有结果数据
* `test_config.json`: 本次基准测试运行使用的配置参数
* `tokens_per_second_metrics_info.txt`: 关于 Tokens/ 指标如何计算的说明
* `prompts_length_*.txt`: 为每个输入长度生成并用于测试的实际提示文本
* `requests/`: 一个子目录包含每个 `token_length_X` `concurrency_Y` 的嵌套文件夹其中包含每个 API 请求的详细日志单个 `request_*.json` 文件)。
* `*.png` 文件 (如果安装了 `matplotlib`): 可视化图表
* 总输出 Tokens/ vs. 并发数
* 平均每请求输出 Tokens/ vs. 并发数
* 成功率 vs. 并发数
## 关键指标说明
* **`total_tokens_per_second` (总吞吐量)**: 计算方式为所有成功的并发请求生成的 `output_tokens` 之和/整个并发批次的总耗时)。这代表了服务器在该特定负载下的整体处理能力
* **`avg_tokens_per_second` (平均每请求吞吐量)**: 计算方式为批次内每个成功请求的 (`output_tokens` / `elapsed_time`) 的平均值这代表了在该负载下单个客户端请求所体验到的平均生成速度
* **注意:** 默认情况下这两个指标都侧重于 **输出 Tokens**因为这通常反映了用户感知的生成速度API 的原始响应保存在单个请求的 JSON 文件 `full_response` 也包含输入 Token 计数 (`usage.prompt_tokens`)。
## 注意事项
* Token 计数的准确性依赖于 API 服务器在响应的 `usage` 字段中正确返回 `prompt_tokens` `completion_tokens`
* `min_tokens` 参数的有效性取决于目标 API 端点是否支持它提示增强是作为一种备用策略
* 如果未安装 `tiktoken`Token 计数将基于字符长度进行近似估算这对于非英语文本或代码来说准确性较低
## 实例
使用下面的命令在 H200 HGX 平台上进行测试
```bash
python vllm_benchmark.py --token-lengths 10 100 500 1000 2000 5000 10000 20000 30000 --concurrency-levels 1 16 64 128 256 512 result
```
结果如下
![](src/avg_tokens_per_second_vs_concurrency.png)
![](src/success_rate_vs_concurrency.png)
![](total_tokens_per_second_vs_concurrency.png)