ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

exo-bench 基准测试方法详解:prompt 定长构造、前缀缓存模式、warmup 与并发聚合 TPS 口径

exo-bench 基准测试方法详解:prompt 定长构造、前缀缓存模式、warmup 与并发聚合 TPS 口径 exo-bench 基准测试方法详解prompt 定长构造、前缀缓存模式、warmup 与并发聚合 TPS 口径【免费下载链接】exoRun frontier AI locally.项目地址: https://gitcode.com/GitHub_Trending/exo8/exoexo-bench 是 exo 自带的基准测试工具用于在受控条件下测量 exo 集群的推理吞吐与资源消耗它向/bench/chat/completions端点发送 prompt采集服务端上报的计时统计并在整个运行期间记录系统级指标功耗、GPU 利用率、温度。当你需要比较不同模型、不同 placement 配置之间的速度与扩展性或者在优化上线后追踪性能变化时前提是搞清楚这些数字到底是怎么算出来的。本文依据 bench/METHODOLOGY.md 的方法论说明和 bench/exo_bench.py 源码逐项讲清 prompt 定长构造、端点行为、TPS 口径、前缀缓存模式与 warmup 机制。运行前提与最短命令README 中 Benchmarking 一节给出的前提所有集群节点在基准测试前应当已在运行uv run exo工具使用的是专用的/bench/chat/completions端点而不是普通的/v1/chat/completions。在仓库根目录执行的基础命令README 示例uv run bench/exo_bench.py \ --model Llama-3.2-1B-Instruct-4bit \ --pp 128,256,512 \ --tg 128,256--pp是 prompt 长度目标token 数支持逗号分隔--tg是生成长度两者长度相等时按顺序一一配对不等时做笛卡尔积--all-combinations可强制笛卡尔积。常用参数均取自exo_bench.py的参数定义参数默认值作用--model必填模型短名或 HuggingFace ID--repeat1每个 (pp, tg) 组合的重复次数--concurrency1并发档位列表例如--concurrency 1,2,4,8--warmup0每个 placement 的预热运行次数--use-prefix-cache关闭基准期间保持 KV 前缀缓存开启--json-outbench/results.json原始逐次运行结果 JSON 的输出路径--stdout关闭把结果写到 stdout--dry-run关闭只列出选中的 placement 并退出--no-system-metrics关闭停止采集 GPU 利用率、温度、功耗--min-nodes/--max-nodes1 / 4限定 placement 使用的节点数--instance-meta/--shardingboth按通信方式ring/jaccl与分片方式pipeline/tensor过滤 placement完整参数列表以--help为准METHODOLOGY.md 结尾的说明。Prompt 定长构造基准测试需要精确 token 长度的 prompt但 bench 客户端只有 chat completion 端点无法直接访问模型。exo-bench 的解法分三步METHODOLOGY.md 的 Prompt Construction 一节先用模型的apply_chat_template()对一条样例消息做 tokenize测量模板开销system token、特殊 token、chat 格式在一个重复的原子串默认a 上二分搜索找到使模板展开后恰好等于目标 token 数的内容长度同时返回内容字符串和验证过的 token 数。实际 token 数会记录在每一行结果里字段名是pp_tokens下游分析可以用它确认 prompt 命中了目标长度。一个已知限制chat 模板的固定开销意味着很小的 pp 目标可能无法命中例如pp32可能跑不了。METHODOLOGY.md 说明这是有意接受的取舍因为过小的 prompt 对真实场景参考价值有限。/bench/chat/completions端点的三个特殊行为请求到达 bench 端点后与一次普通 chat completion 相比有三处变化KV 前缀缓存默认关闭。每个请求都从冷缓存开始保证 prefill 计时不受先前请求影响。EOS token 被禁用。一个 logits processor 会抑制所有结束符强制模型恰好生成max_tokens个 token保证生成长度一致、TPS 可比——模型无法靠提前停止抄近路。不做模型输出解析。bench 采集路径直接拼接原始 token 文本没有 thinking 标签提取、结构化输出处理等模型专属后处理避免工具解析或结构性错误把基准测试弄挂。METHODOLOGY.md 的口径是这里只测速度质量类指标归 exo-eval。Prefill 与 Generation TPS 的计算口径两项 TPS 都由服务端按 task 测量prefill_tps num_prompt_tokens / prefill_wall_seconds生成阶段每个 token 到达时都打时间戳记录第一个 token 的时间之后每个 token 更新时间。生成完成时gen_span last_token_time - first_token_time generation_tps (completion_tokens - 1) / gen_span分子减去 1 是因为速率衡量的是 token 之间的吞吐——首尾时间间隔除以区间数。直接推论是tg1不可用只有一个 token 时没有区间可测。单请求场景下客户端还会记录整个 HTTP 往返的 wall-clockelapsed_s网络延迟 服务端 prefill 生成 响应序列化这只是端到端延迟的便利指标权威的 TPS 数字来自响应里generation_stats的服务端逐 task 计时。并发测试与聚合 TPS 口径--concurrency NN 1时所有 N 个请求必须同一时刻打到服务端。机制如下prompt 只构造一次在所有线程间共享每个线程持有自己的 HTTP 连接线程屏障threading barrier阻塞所有线程直到每个线程就绪先过屏障的线程记录批次开始时间并通知其余线程所有线程以同一个开始时间作为参照发出 HTTP 请求每个线程的elapsed_s从共享开始时间算到它自己的响应完成。批次 wall time取 N 个请求elapsed_s的最大值即最后一个请求完成所用的时间。聚合吞吐的公式per_req_tps max(generation_tps across N concurrent requests) agg_gen_tps per_req_tps * concurrency这里刻意用max而不是mean所有请求并行打到同一个模型上最快请求的生成速率代表系统的单流吞吐能力乘以并发数得到聚合吞吐。运行日志会打印每个并发档位的agg_gen_tps、per_req_tps、wall_s与错误数例如文档口径下的输出形式[concurrent 4x] agg_gen_tps... per_req_tps... wall_s... errors...上面省略号处为按实际运行生成的数值METHODOLOGY.md 未给出固定示例值。前缀缓存模式--use-prefix-cache与prefix_cache_hit默认关闭前缀缓存是为了测冷 prefill当测的不是 prompt 处理而是生成吞吐或功耗在多组配置间反复跑时--use-prefix-cache可以让 KV 前缀缓存保持激活跳过重复的 prefill 工作。每个响应的generation_stats里带prefix_cache_hit字段取值none、partial、exact定义见 src/exo/api/types/api.py 的GenerationStatsnone冷 prefill没有可用的缓存 KV 状态报告的prompt_tps是真实 prefill 吞吐partialprompt 的前缀命中了缓存只 prefill 剩余 token。典型场景是递增的--pp值共享前缀例如--pp 1000,5000——5000 token 的 prompt 复用 1000 token 的缓存条目只 prefill 剩余 4000 token报告的prompt_tps是未缓存部分上的真实吞吐exact整个 prompt 都在缓存里例如--repeat时用同一个--pp值本次没有做 prefill 工作报告的prompt_tps是缓存条目最初创建时的 TPS不是新测量值。因此前缀缓存模式下 prompt TPS 是近似的。要准确的冷 prefill 数字必须不带--use-prefix-cache运行。递增的--pp顺序如--pp 1000,5000,10000最有价值除第一个是冷命中外每个尺寸都能得到有意义的 partial 命中递减顺序则产生 exact 命中TPS 只是长 prompt 最初那次运行的近似值。工具在--use-prefix-cache且--pp非升序时会主动打印警告。一个开启前缀缓存的示例组合参数均见exo_bench.py定义uv run bench/exo_bench.py \ --model Llama-3.2-1B-Instruct-4bit \ --pp 1000,5000,10000 \ --tg 128 \ --use-prefix-cacheWarmup 与结果输出--warmup N默认 0会在正式测量开始前用第一对pp/tg 发送 N 个丢弃请求warmup 结果不计入输出。METHODOLOGY.md 的完整复现示例即带--warmup 1cd bench uv run python exo_bench.py \ --model mlx-community/Qwen3.5-27B-4bit \ --instance-meta jaccl \ --sharding tensor \ --min-nodes 2 --max-nodes 2 \ --pp 512 4096 --tg 128 \ --repeat 3 \ --warmup 1结果以 JSON 写出三个顶层键runs逐请求结果数组每行包含elapsed_s、output_text_preview前 200 字符、statsprompt_tps、generation_tps、prompt_tokens、generation_tokens、peak_memory_usage、power_usage服务端总量 prefill/生成拆分 每节点拆分仅非流式请求、placement 元数据model_id、placement_sharding、placement_instance_meta、placement_nodes、运行元数据pp_tokens、tg、repeat_index、concurrency、concurrent_index以及模型新下载时的download_duration_scluster基准时刻的集群状态快照system_metrics每节点的时间序列采样GPU、功耗、温度。系统指标由后台线程以 1 Hz--metrics-interval可调轮询每个节点采集 GPU 利用率、温度、整机功耗和 CPU 大小核占用能量对每个推理窗口内的功耗采样做梯形积分平均功率为total_joules / total_inference_seconds。结果验证与边界拿到结果 JSON 后验证口径如下用每行的pp_tokens核对 prompt 是否命中--pp目标看prefix_cache_hit判断该行的prompt_tps是否为真实冷测量——exact命中的行只应理解为缓存创建时的历史 TPS用stats.generation_tps与并发日志里的agg_gen_tps对照聚合口径不确定 placement 过滤是否选对时先跑--dry-run它会列出选中 placement 后直接退出不产生任何实例。需要注意的执行行为与边界来自exo_bench.py与 tools/src/exo_tools/harness.py 的源码工具会自动创建受测实例并在每个 placement 运行后删除放置新实例前它会先删除集群里已存在的实例以释放资源——运行前确认集群上没有你正在使用的其他实例磁盘不足时默认报错退出加上--danger-delete-downloads后它会按从小到大删除已有的模型下载来腾出空间该标志会删除其他模型的下载文件仅在确认可以清理时使用tg1不可用无 token 区间可测过小的--pp可能因模板开销无法命中目标--stream会走 SSE 流式响应此时没有服务端power_usage拆分generation_stats缺失时由客户端自行估算。METHODOLOGY.md 同时声明方法论和基准工具本身会随时间变化该文档会随变更保持更新发现问题或想加特性可以通过 GitHub issue 反馈。【免费下载链接】exoRun frontier AI locally.项目地址: https://gitcode.com/GitHub_Trending/exo8/exo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表