ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

大模型推理基准测试入门:延迟、吞吐量与显存占用怎么测

大模型推理基准测试入门:延迟、吞吐量与显存占用怎么测 开头前两段自然段都要长。下面正文。文章的标题不需要单独一级标题CSDN可以用标题通常博主有一个一级标题但用户要求“不需要输出一级标题直接从正文开始”。好的。现在起草并估算长度。我尽可能充实。注意标题编号格式“## 1. ...”。小节编号如“### 1.1 ...”。开篇段约为300字。确保不要输出“以下是一个方法”“你好”。直接开头。Lets write final in Chinese.这次我们来把“LLM Inference Benchmarking”这件事说清楚。它不是一个模型也不是某一张跑分榜单而是一整套围绕大模型推理链路的测试方案服务用什么框架启动模型放进哪张显卡并发请求怎么打上下文长度拉到多少显存是否足够首字返回需要多久单位时间能产出多少 token。这些指标直接决定一个自部署推理服务能不能接进业务也决定你在买卡、换模型、调量化参数时到底该看什么。如果你只是单条 prompt 试一下“能输出就行”根本看不出来服务是快是慢。真正做容量评估或横向对比时必须用固定模型、固定输入、固定并发数去压测分别记录首 token 延迟、端到端延迟、吞吐量、成功率和显存占用。这篇文章不写虚拟跑分也不列谁家“秒杀谁”的结论而是给出一套可以在本机复现的推理基准测试方法先搭好环境再启动 vLLM、Ollama、llama.cpp 这类常见服务然后用 HTTP API 打请求把指标落成表格。按这个流程走完你手里会有一套自己的 baseline。这篇文章适合三类读者第一类是自己部署开源模型、想评估服务能不能上线的应用开发者第二类是打算做模型选型、需要对比不同量化方式和上下文长度的人第三类是刚接触大模型推理想搞清楚 TTFT、吞吐量、KV Cache、显存占用这些概念到底怎么测的运维或算法工程师。下面直接进入正题。1. LLM 推理基准测试到底是测什么1.1 推理性能基准和模型能力基准是两回事先区分两个很容易混的概念。我们经常看到的 MMLU、GSM8K、HumanEval、C-Eval 这类榜单测的是模型“会不会”知识储备、推理能力、代码能力。它们会给你一个准确率分数比如数学基准 85 分、代码基准 70 分。这类测试通常跑一条推理也不关心花了多久、占了多少显存。而 LLM Inference Benchmarking 测的是运行性能首 token 延迟多高、输出吞吐多大、能不能支撑 8 路并发、显存会不会爆、模型的工程实现是否稳定。同一个模型换不同推理框架、换不同量化格式、换不同 max_model_len结果可能差异很大。所以能力榜单解决“选哪个模型”推理基准解决“模型跑起来快不快、能不能接业务”。1.2 推理基准里的核心指标指标缩写衡量内容对使用体验的影响首 token 延迟TTFT从发送请求到返回第一个 token 的时间决定用户感知的“响应是否慢”端到端延迟E2E Latency从发送请求到完整回答返回的时间决定单次请求的总耗时输出吞吐量Tokens/s单位时间内模型实际生成的 token 数决定批量任务的处理能力并发成功率Success Rate在指定并发下成功返回的请求占比决定服务是否稳定可用KV Cache 显存占用KV Cache缓存历史 token 注意力计算结果的显存决定能支持的并发和上下文长度显存峰值VRAM Peak推理过程中 GPU 显存最高值决定当前显卡能不能扛住当前配置在能力榜单上一个 7B 模型可能比一个 13B 模型分数低但在推理性能上更小模型经常能提供更低延迟和更高吞吐。具体怎么取舍取决于业务对实时性和输出质量的要求。1.3 什么时候必须做推理基准测试以下场景建议不要凭感觉判断直接跑一次基准测试两个模型在同一个业务场景都可用需要根据响应速度选型同一个模型有 FP16、INT8、INT4 等量化版本想确定哪种格式在本机效果最好准备上线接口服务需要确认能支持多大的并发批量任务在夜间跑需要估算跑完 10 万条文本要多久换显卡、换机器后需要确认推理速度是否达到预期。2. 核心能力速览因为 LLM Inference Benchmarking 是方法论而非单仓库项目我先用一张表把整套方案覆盖的内容列清楚。项目主题LLM Inference Benchmarking测试目标测量大模型推理服务的延迟、吞吐、并发能力和显存占用常用待测后端vLLM、Ollama、llama.cpp、Hugging Face TGI 等常见 APIOpenAI 兼容/v1/chat/completions、Ollama/api/generate、llama.cpp/completion推荐硬件有 NVIDIA GPU 的 Linux/WSL 环境最顺手无 GPU 也可先用 llama.cpp CPU 模式验证链路显存需求取决于模型参数量、量化格式、上下文长度和并发数没有通用固定值批量任务支持通过脚本循环发送本地任务列表或调用离线批处理接口启动方式命令行启动推理服务脚本读取 HTTP API 发起压测主要输出TTFT、E2E、总 tokens/s、成功率、显存峰值、P50/P95 延迟适合场景自部署评估、容量规划、模型选型、量化效果对比、上线前稳定性验证本机 GPU 显存不足时不要把“推理基准测试”和“大模型推理”混为一谈。压测的本质是服务端能力摸底所以你可以先用小模型、短提示词把整套流程跑通再逐步加大输入长度和并发数。3. 适用场景与使用边界3.1 适合谁这个方案对以下几类团队价值最高。一是做本地知识库或 Agent 应用的开发者。你需要知道接口在并发打到 10 时是否超时一条 8000 字的长文档进入上下文后生成速度会不会被拖慢。二是做模型部署的运维工程师。你们最关心的是模型加载时间、最大并发、显存余量和整体吞吐这些数据在上线前必须产出。三是做技术选型的产品或算法同学。你们需要在评测报告里写清楚A 模型在低并发下延迟低B 模型在高并发下吞吐高不同量化的效果差异到底有多少。对个人学习者也适合因为现在很多本地推理框架已经非常轻量Ollama 在不同操作系统上都有客户端llama.cpp 也支持 CPU 推理。即使没有高端显卡你也可以用 2G 显存或纯 CPU 跑一个小模型先把压测方法练熟。3.2 不适合什么场景如果你只是想看模型“懂不懂某个问题”直接对话验证即可不需要跑基准测试。如果你需要的是能力碾压的权威榜单那应该去做 MMLU 等标准测试而不是本机推理压测。另外如果硬件环境波动很大比如虚拟机 CPU 核数不固定、显卡被多个容器共享那么压出来的数字参考价值有限更适合做相对对比而不是绝对结论。3.3 使用边界与合规提醒在自部署推理链路中输入数据完全留在本机相比调用公共 API 有隐私优势。但要注意几点不要在未确认授权的情况下把内部业务文档、合同、客户隐私数据直接灌进模型测试完成后要清理日志不要因为跑压测就把推理服务暴露到公网本地验证默认绑定127.0.0.1即可如果要把输出用于商用需要确认模型权重本身的开源许可允许商用不能只根据框架能跑就默认授权。涉及代码、人脸、声音、版权素材的场景必须分别确认数据来源合法。这里不展开具体法律建议安全第一。4. 环境准备与前置条件在开始压测前先整理一套干净的最小测试环境。4.1 操作系统与显卡驱动vLLM 对 Linux 环境最友好Windows 用户可以优先考虑 WSL2 或者直接在 Windows 上用 Ollama/llama.cpp。NVIDIA 用户先检查驱动和 GPU 是否能被识别。nvidia-smi如果命令不存在说明驱动没装好命令存在则能列出显卡型号、驱动版本和当前显存使用。自部署推理时驱动版本需要满足推理框架要求的 CUDA 版本具体版本号以你使用的 vLLM、PyTorch 官方安装说明为准不要只看系统里有没有 CUDA 这个单词。4.2 模型文件准备不同推理后端使用的模型格式不同后端常见模型格式说明vLLMHugging Face 格式目录包含 config.json 与权重文件需要先下载到本地OllamaOllama 模型标签通过ollama pull拉取会按标签管理llama.cppGGUF 单文件格式适合量化部署模型文件通常只有一个.gguf为了减少外部环境影响压测时把所有模型文件放在统一目录比如/models。同时记录模型标签或目录名因为在结果里只写“7B 模型”没有意义必须是“Qwen2.5-7B-Instruct 的某种量化版”或“某个检查点的版本号”。4.3 磁盘和内存检查模型下载和加载都需要空间。一个 7B FP16 模型权重大约 14GB实际加载时还要考虑临时缓存和前后端内存因此磁盘至少留两倍权重空间内存也要足够加载整个权重。GGUF 量化的模型体积会明显更小比如 INT4/INT8 量化后文件体积会低很多。这里的空间需求只做规划参考应以你实际下载模型的仓库说明为准。4.4 Python 虚拟环境压测脚本依赖 Python为了保证环境干净建议创建独立虚拟环境。python -m venv .venv source .venv/bin/activate如果使用 vLLM在 Linux 环境通过 pip 安装即可但不同版本对 CUDA 和 Python 有不同要求建议先看官方安装页。Ollama 和 llama.cpp 则不一定在 Python 环境里启动它们作为独立服务运行Python 只负责后续发 HTTP 请求。压测脚本至少需要requests没有安装就执行pip install requests5. 推理服务部署与启动5.1 选一个固定的推理后端如果你的目的是“给已经跑起来的服务做压测”直接跳过本小节从第 5.2 节开始。如果你还没有推理服务先选择一个后端。不同后端侧重点不同。后端启动复杂度适用方向vLLM中等推荐 Linux GPU 环境高并发、生产环境、OpenAI 兼容 APIOllama低跨平台快速体验、单机小规模、本地知识库llama.cpp中低跨平台CPU/GPU 混合推理、GGUF 量化、轻量部署基准测试最关键的一点是对比时只改一个变量。比如都是同一个模型都跑同一个 promptA 后端和 B 后端才能对拍。不要用 A 模型跑 vLLM、B 模型跑 Ollama然后把结果拿来比那会混入模型差异。5.2 使用 vLLM 启动 OpenAI 兼容服务以 vLLM 为例先把模型下载到/models目录然后启动服务。vllm serve /models/Qwen2.5-7B-Instruct \ --served-model-name my-model \ --host 127.0.0.1 \ --port 8000 \ --max-model-len 8192这里的模型路径和模型名都要按实际情况替换。启动成功后可以访问服务自带的模型列表接口来确认curl http://127.0.0.1:8000/v1/models如果返回 JSON 里包含id: my-model说明服务已经起来后面的压测请求就可以直接指向http://127.0.0.1:8000/v1/chat/completions。5.3 使用 Ollama 或 llama.cpp 作为轻量后端Ollama 的启动方式更简单ollama serve ollama pull 模型标签 ollama run 模型标签首次拉取模型需要一定时间具体标签以模型仓库为准。跑通后Ollama 会提供原生的/api/generate接口也提供部分 OpenAI 兼容端点。如果需要更细粒度的后端控制可以用 llama.cpp 系列工具启动 GGUF 模型llama-server \ -m /models/your-model.gguf \ -c 4096 \ --host 127.0.0.1 \ --port 8080llama.cpp 的二进制名称在不同版本中可能叫llama-server或server参数也可能略有差异老版本和新版本之间要按实际编译产物调整。启动成功后可以请求它的/health或直接调/completion。5.4 服务连通性检查不管用哪个后端压测前都要先做一次最小连通性验证。先不写完整脚本直接用手工 curl 请求一个 chat 补全接口。curl http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: my-model, messages: [ {role: user, content: 用两句话介绍什么是 LLM 推理} ], max_tokens: 100, temperature: 0 }这里的接口路径和字段针对 OpenAI 兼容格式如果你用的是 Ollama 原生接口或 llama.cpp 原生接口字段名会不同例如模型名字段可能叫model但返回结构不是choices而是response或content。建议以单个后端启动后的实测输出为准。6. 设计一套可复现的推理基准测试流程6.1 固定压测参数可复现是基准测试的基本要求。压测前必须先固定下面这些参数参数建议固定方式模型记录模型名称、权重格式、量化方式输入 prompt使用固定文本避免每次请求的内容不同上下文长度固定max_model_len或ctx_size输出上限固定max_tokens但记录实际输出 token 数并发数从 1 开始再按 4、8、16 逐步增加请求总数每个并发档位固定跑 N 次不以“跑 3 秒”为准采样参数建议temperature 0或固定值降低随机性需要说明的是设置max_tokens并不代表每条请求都会输出那么多 token。模型可能提前结束。因此压测脚本应从返回的 usage 字段中读取completion_tokens而不是用max_tokens直接当作输出量。6.2 先热身后正式测试模型刚加载完时权重进入 GPU 显存但很多内部状态尚未稳定第一次请求往往比后续请求慢。所以压测正式开始前先发 1 到 2 次“热身请求”确认服务能正常返回然后再记录正式数据。每个并发档位至少跑 10 到 20 个请求否则结果方差很大。对正式对比建议同一档位重复 3 轮最后取中位数或 P95而不是只看最好的一次。6.3 记录环境指纹每组结果都要记录环境信息否则隔几天回来完全不知道这个数字是在什么条件下测的。建议在结果文件中包含日期、GPU 型号、驱动版本、推理框架版本、模型名称、量化格式、并发数、请求总数、上下文长度、max_tokens、成功请求数、失败请求数、总耗时、总生成 token 数、显存峰值。这一条在容量评估时尤其重要因为同一个模型在不同驱动版本下的表现也可能有差异。7. 编写 API 压测脚本下面给一个最小可用的 Python 压测脚本。它使用线程池模拟并发请求记录每个请求的端到端耗时和返回 token 数最后统计成功率和有效吞吐。7.1 OpenAI 兼容接口的并发吞吐脚本import json import statistics import threading import time from concurrent.futures import ThreadPoolExecutor import requests API_URL http://127.0.0.1:8000/v1/chat/completions MODEL my-model PROMPT 请写一段较长的技术说明介绍自部署大模型推理时需要考虑的因素。 CONCURRENCY 8 TOTAL_REQUESTS 32 MAX_TOKENS 512 results [] lock threading.Lock() def send_one(_): payload { model: MODEL, messages: [{role: user, content: PROMPT}], max_tokens: MAX_TOKENS, temperature: 0, } start time.time() try: resp requests.post( API_URL, jsonpayload, headers{Content-Type: application/json}, timeout(30, 600), ) elapsed_ms (time.time() - start) * 1000 if resp.status_code ! 200: with lock: results.append( { ok: False, status: resp.status_code, error: resp.text[:300], elapsed_ms: elapsed_ms, } ) return data resp.json() usage data.get(usage, {}) completion_tokens usage.get(completion_tokens, 0) content try: content data[choices][0][message][content] except Exception: pass with lock: results.append( { ok: True, status: resp.status_code, completion_tokens: completion_tokens, elapsed_ms: elapsed_ms, content: content, } ) except Exception as exc: elapsed_ms (time.time() - start) * 1000 with lock: results.append( { ok: False, status: -1, error: str(exc), elapsed_ms: elapsed_ms, } ) start_all time.time() with ThreadPoolExecutor(max_workersCONCURRENCY) as executor: executor.map(send_one, range(TOTAL_REQUESTS)) wall_time time.time() - start_all success [r for r in results if r[ok]] failed [r for r in results if not r[ok]] total_output_tokens sum(r.get(completion_tokens, 0) for r in success) latencies [r[elapsed_ms] for r in success] print(并发数:, CONCURRENCY) print(请求总数:, TOTAL_REQUESTS, 成功:, len(success), 失败:, len(failed)) print(成功率: %.2f%% % (100.0 * len(success) / TOTAL_REQUESTS)) print(总墙钟时间: %.2f s % wall_time) print(总输出 token 数:, total_output_tokens) if wall_time 0: print(整体吞吐: %.2f tokens/s % (total_output_tokens / wall_time)) if latencies: latencies.sort() p50 statistics.median(latencies) p95 latencies[min(int(len(latencies) * 0.95) - 1, len(latencies) - 1)] print(E2E 延迟中位数 P50: %.2f ms % p50) print(E2E 延迟 P95: %.2f ms % p95) with open(bench_result.jsonl, w, encodingutf-8) as f: for r in results: f.write(json.dumps(r, ensure_asciiFalse) \n)脚本是按 OpenAI 兼容接口写的。如果你用的是 Ollama/api/generate返回体里面通常没有usage.completion_tokens可以去找eval_count字段如果你用的是 llama.cpp 原生/completion可以在timings.predicted_n里找到生成 token 数。改脚本时要先打印一条原始返回 JSON确认字段名再改不要想当然。7.2 测量首 token 延迟上面的脚本测的是端到端总耗时。如果还想知道“用户发出请求后多久看到第一个字”最好的做法是把请求改成流式模式。这里只给一个最小思路import json import time import requests API_URL http://127.0.0.1:8000/v1/chat/completions payload { model: my-model, messages: [{role: user, content: 请输出一段较长的内容。}], max_tokens: 512, stream: True, temperature: 0, } start time.time() with requests.post( API_URL, jsonpayload, headers{Content-Type: application/json}, timeout(30, 600), streamTrue, ) as resp: first_token_latency_ms None for line in resp.iter_lines(): if not line: continue if line.startswith(bdata:): chunk_data line[len(bdata:) :].strip() if chunk_data b[DONE]: break chunk json.loads(chunk_data) delta chunk.get(choices, [{}])[0].get(delta, {}) if delta.get(content): first_token_latency_ms (time.time() - start) * 1000 break if first_token_latency_ms is not None: print(TTFT: %.2f ms % first_token_latency_ms) else: print(未捕获首 token请确认服务端支持 SSE 流式输出)不同后端对流式 SSE 的实现细节有差异有的后端第一行会先返回空的 role 块有的会在 delta 里返回reasoning_content。所以代码里要先做空值判断实在抓不到首个 content 时不要直接失败可以先打印前几行原始数据定位。7.3 批量任务测试推理基准压测和批量任务的关系很紧密。批量任务关注的不只是单次接口性能还有整批任务的完成时间、失败重试和进度记录。最简单的方式是把待处理提示词放到一个 JSONL 文件然后逐条发送import json import time import requests INPUT_FILE prompts.jsonl OUTPUT_FILE batch_result.jsonl API_URL http://127.0.0.1:8000/v1/chat/completions MODEL my-model MAX_RETRY 3 with open(INPUT_FILE, r, encodingutf-8) as f: prompts [json.loads(line) for line in f if line.strip()] with open(OUTPUT_FILE, w, encodingutf-8) as out: for idx, item in enumerate(prompts): prompt item[prompt] for attempt in range(1, MAX_RETRY 1): try: resp requests.post( API_URL, json{ model: MODEL, messages: [{role: user, content: prompt}], max_tokens: item.get(max_tokens, 1024), temperature: 0, }, timeout(30, 600), ) if resp.status_code 200: record { idx: idx, ok: True, attempt: attempt, response: resp.json(), } out.write(json.dumps(record, ensure_asciiFalse) \n) out.flush() break else: raise RuntimeError(resp.text[:200]) except Exception as exc: if attempt MAX_RETRY: record { idx: idx, ok: False, attempt: attempt, error: str(exc), } out.write(json.dumps(record, ensure_asciiFalse) \n) out.flush() else: time.sleep(2 * attempt)这个脚本没有做并发适合先验证批量链路。如果要大批量并发执行可以复用 7.1 节的线程池思路但要把进度和重试逻辑融进去。更完整的生产级方案一般会引入任务队列不过对绝大多数自部署场景先用 JSONL 加断点续跑就够用。7.4 批量任务与推理压测之间的关系批量任务里最常见的坑是任务一上来就全量高并发结果服务端 OOM 或限流任务失败记录没有落盘跑了一晚上等于白跑。正确思路是先小批量试 2 到 3 条确认返回结构和 token 数再放大并发。同时在批量任务中记录每条任务的耗时和失败原因方便失败后重跑。按这个方式批量任务本身就是在做一次长时间的低成本推理基准测试。8. LLM 推理资源占用与性能观察8.1 用 nvidia-smi 观察显存与 GPU 利用率压测过程中建议单独开一个终端持续观察显存变化不要只看压测结束后的瞬时值。nvidia-smi --query-gpumemory.used,memory.total,utilization.gpu,temperature.gpu --formatcsv -l 1这个命令会每秒输出显存占用、GPU 利用率和温度。压测开始前记录一次空闲显存请求并发打上去之后再记录峰值。如果显存一直顶到接近物理上限即使当前压测没挂后续一旦输入文本变长或并发增加仍然可能触发 OOM。8.2 怎么判断显存够不够这里需要区分模型权重显存和运行时 KV Cache 显存。模型权重大小基本是固定的FP16 格式下权重显存大约等于权重文件体积KV Cache 则随着上下文长度、batch 大小和层数变化。一个模型能支持多少并发很大程度取决于 KV Cache 还能占多少显存。更稳妥的判断方法是观察服务端日志中显存上限参数和实际 KV Cache 占用而不是只在外面看nvidia-smi。如果你确实发现显存不够优先做四件事缩短max_model_len、减少并发数、降低 batch 大小、换一个更激进的量化格式。8.3 观察 CPU、内存和启动时间GPU 推理服务并不是完全不吃 CPU 和内存。模型加载阶段会先把权重从磁盘读进内存再加载到显存所以加载阶段内存和磁盘 IO 会明显升高。压测过程中如果使用纯 CPU 推理吞吐通常会低于 GPU如果使用 GPU 推理但 CPU 线程数不够也可能出现 prefill 阶段处理慢的情况。建议在压测命令执行的同时开一个htop或top观察多核占用。启动时间也要记录因为模型文件越大、量化越保守启动和冷启动时间越长。8.4 从服务端日志确认生成速度很多推理框架在日志里会打印 prefill 耗时和 decode 速度这是比客户端更准确的性能来源。因为客户端脚本的延迟包含了网络传输和请求排队时间而服务端日志只统计模型处理耗时。压测结束后把客户端统计和服务端日志同时保存能帮助你判断瓶颈究竟在网络、服务排队还是模型本身。9. 常见问题与排查方法压测过程中会遇到的典型问题很多不是模型能力问题而是工程配置问题。问题现象可能原因排查方式解决方案服务启动后请求报 404模型名或接口路径不对访问/v1/models看模型 ID把请求体里的 model 改成实际模型名第一次请求非常慢甚至超时模型权重正在加载或 KV Cache 初始化查看服务端日志预热一次再开始正式压测GPU 显存不足直接报错模型权重加上 KV Cache 超出物理显存用 nvidia-smi 查看显存缩短上下文、降并发、换量化模型并发一高就大量失败服务端 batch 过大或请求超时观察服务端日志和显存曲线降低并发档位或提高后端并发上限CUDA 版本或驱动不匹配环境未满足推理框架要求查看 nvidia-smi 与框架安装文档升级驱动或使用对应 CUDA 的容器输出为空或乱码采样温度过高或 tokenizer 不匹配先固定 temperature0 测试换正确指令模板和 tokenizerAPI 返回 429服务端有限流或队列已满检查服务端日志降低压测速率增加重试逻辑压测结果波动很大热身不足、共享 GPU、输入文本不同固定 prompt 并跑多轮做 3 轮取中位数记录环境指纹端口被占用之前有服务残留进程检查端口占用换端口或清理旧进程流式输出卡住没有设置超时或返回格式不兼容打印原始流式响应的前几行调整 timeout 并兼容后端 SSE 格式很多人遇到“推理服务启动了但压测接口却打不开”的情况第一反应是怀疑脚本写错。实际上先检查端口和进程更高效。ss -lntp | grep 8000如果端口没有监听说明服务进程没有正常起来如果端口有监听但访问失败再用 curl 手工请求定位服务端返回的异常信息。越早拆掉“服务本身问题”和“压测脚本问题”越容易继续。10. 最佳实践与推理基准测试的使用建议10.1 先跑一条最小链路第一次部署推理服务时不要直接上 7B 甚至 13B 模型。先挑一个几百 MB 的小模型或小量化版本把启动服务、手工 curl、Python 请求三件事全部跑通再切换到正式模型。这样可以避免在“模型权重下载”“格式不兼容”“显存不够”等问题里纠缠。10.2 一次只改一个变量模型和推理框架的变量非常多模型名称、量化方式、KV Cache 上限、并发数、输入长度、输出 max_tokens、采样参数。每轮压测只改一个变量其他全部保持不变否则结果无法归因。今天换了模型又换了 max_model_len延迟变慢后你根本不知道是谁拖慢了。10.3 用目录管理测试产物建议建立固定目录结构llm-bench/ ├── inputs/ # 压测 prompt 集、批量任务原始文本 ├── models/ # 模型权重或符号链接 ├── results/ # 压测结果 JSONL 和汇总报告 ├── logs/ # 服务端日志、运行脚本输出 └── scripts/ # 启动脚本和压测脚本模型文件、输入数据和输出结果分开能避免把测试输入混进生产目录也方便后续清理隐私数据。10.4 为批量任务加日志和重试批量任务长时间运行失败不可避免。每个请求的序号、耗时、状态、错误信息和重试次数都要写入结果文件。重试策略建议使用指数退避比如第一次失败等 2 秒第二次等 4 秒不要把请求无限并发地打在已经超时的服务上。任务跑完后检查失败列表并单独重跑失败样本而不是整批从头再来。10.5 服务访问控制与安全边界压测脚本和推理服务默认只绑定本机地址。如果需要远程访问建议通过认证、反向代理或内网环境不要直接把无鉴权的推理服务暴露到公网。压测数据如果包含内部业务信息在生成报告前要做脱敏处理测试完清理临时文件。对别人开发的模型要注意模型许可证对商用和派生用途的限制。10.6 写一份可追溯的基准报告建议在每次基准测试后生成一个简洁的 Markdown 报告至少包含以下字段报告字段示例测试日期2025-06-20GPU 型号示例NVIDIA 显卡具体型号以实际为准推理框架及版本vLLM x.y.z模型与量化格式模型名称 AWQ / FP16 / GGUF Q4并发数1 / 4 / 8 / 16请求总数32上下文长度4096成功率100%整体吞吐tokens/sE2E P50 / P95毫秒没有上下文和版本的 token/s 数字很难有参考价值报告的作用不是追求好看的数值而是让未来的你能准确复现和对比。11. 总结与下一步回到开头的结论LLM Inference Benchmarking 的价值不在于跑一个漂亮的数字而在于让模型部署从“感觉能用”变成“可比较、可验收”。你可以先选一个轻量后端跑通最小链路然后固定一个模型和一组 prompt用不同并发档位分别记录 TTFT、E2E、吞吐、成功率和显存峰值。数据出来之后再决定是否换量化、是否加长上下文、是否需要横向扩展多卡。最容易踩的坑是没记录环境信息就直接比数字其次是并发一上来就去打大模型导致 OOM。把目录结构、模型版本、服务日志和结果一起保存后面每一次换卡、换模型、换框架都能直接在这套架子上做对比。建议把这篇文章的思路改成你自己的脚本作为后续所有大模型推理选型和容量规划的起点。
返回列表