前言模型训练出来只是第一步让它稳定高效地服务线上请求才是真正的 challenge。这篇文章覆盖模型部署的完整流程——从模型导出到生产级推理服务。Step 1模型导出与格式转换PyTorch → ONNXONNXOpen Neural Network Exchange是模型部署的中间格式几乎所有的推理框架和硬件都支持它。importtorchimporttorch.onnx modelYourModel()model.eval()dummy_inputtorch.randn(1,3,224,224)torch.onnx.export(model,dummy_input,model.onnx,input_names[input],output_names[output],dynamic_axes{input:{0:batch_size},output:{0:batch_size},},opset_version17,)关键参数dynamic_axes声明哪些维度是可变的比如 batch_size 和序列长度opset_version越高支持的算子越多但硬件兼容性可能下降。推荐 17-19ONNX 优化导出的 ONNX 模型可以用onnxruntime做优化python-monnxruntime.tools.convert_onnx_models_to_ort model.onnx或者在代码中优化importonnxruntimeasortimportonnxfromonnxruntime.transformersimportoptimizer optoptimizer.optimize_model(model.onnx,model_typebert,# 根据模型类型选择num_heads12,hidden_size768,opt_level99,# 最大优化)opt.save_model_to_file(model_optimized.onnx)优化效果一般能提升 1.5x-3x 的推理速度。检查 ONNX 模型的正确性# 验证输出一致性withtorch.no_grad():torch_outputmodel(dummy_input).numpy()ort_sessionort.InferenceSession(model.onnx)ort_input{ort_session.get_inputs()[0].name:dummy_input.numpy()}ort_outputort_session.run(None,ort_input)# 检查误差diffnp.abs(torch_output-ort_output[0]).max()print(fMax diff:{diff})# 对于 FP32diff 1e-5 是正常的# 对于 FP16/INT8diff 1e-2 是可接受的Step 2推理加速 —— TensorRTTensorRT 是 NVIDIA 的推理优化引擎可以在 GPU 上达到极致性能。ONNX → TensorRTimporttensorrtastrt loggertrt.Logger(trt.Logger.WARNING)buildertrt.Builder(logger)networkbuilder.create_network(1int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))parsertrt.OnnxParser(network,logger)withopen(model.onnx,rb)asf:parser.parse(f.read())configbuilder.create_builder_config()config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE,130)# 1GB# FP16 精度精度几乎无损速度提升 2xifbuilder.platform_has_fast_fp16:config.set_flag(trt.BuilderFlag.FP16)# INT8 量化需要校准数据集速度再提升 2x# config.set_flag(trt.BuilderFlag.INT8)enginebuilder.build_serialized_network(network,config)withopen(model.trt,wb)asf:f.write(engine)精度与速度权衡精度推理速度模型大小质量影响适用场景FP321x100%无基准、调试FP161.5-2x50%几乎无生产推荐INT83-4x25%轻微对延迟极度敏感INT45-6x12.5%明显边缘设备通用建议FP16 是性价比最高的选择。INT8 需要校准数据集且对某些模型有精度风险。TensorRT 推理importtensorrtastrtimportpycuda.driverascudaclassTRTInference:def__init__(self,engine_path):loggertrt.Logger(trt.Logger.WARNING)withopen(engine_path,rb)asf:self.enginetrt.Runtime(logger).deserialize_cuda_engine(f.read())self.contextself.engine.create_execution_context()# 分配 GPU 内存self.inputs[]self.outputs[]foriinrange(self.engine.num_io_tensors):nameself.engine.get_tensor_name(i)shapeself.engine.get_tensor_shape(name)sizetrt.volume(shape)dtypetrt.nptype(self.engine.get_tensor_dtype(name))# 分配内存...# 完整代码见注definfer(self,input_numpy):self.inputs[0].hostinput_numpy.astype(np.float32)[cuda.memcpy_htod(inp.device,inp.host)forinpinself.inputs]self.context.execute_v2([inp.deviceforinpinself.inputsself.outputs])[cuda.memcpy_dtoh(out.host,out.device)foroutinself.outputs]returnself.outputs[0].hostStep 3推理服务框架三种主流方案对比框架适用场景特点Triton Inference Server多模型混合、A/B 测试NVIDIA 官方支持多种硬件和框架vLLMLLM 推理7B-70BPagedAttention连续批处理SGLangLLM 推理结构化输出RadixAttentionJSON Mode用 vLLM 部署 LLMfromvllmimportLLM,SamplingParams llmLLM(modelmeta-llama/Llama-3.2-3B,tensor_parallel_size1,# 单卡部署gpu_memory_utilization0.9,# GPU 显存利用率max_num_seqs256,# 最大并发序列数enable_prefix_cachingTrue,# 前缀缓存加速)sampling_paramsSamplingParams(temperature0.7,top_p0.9,max_tokens1024,)outputsllm.generate([请解释什么是 Transformer],sampling_params)print(outputs[0].outputs[0].text)生产部署用 OpenAI 兼容 APIpython-mvllm.entrypoints.openai.api_server--modelmeta-llama/Llama-3.2-3B--port8000--gpu-memory-utilization0.9然后直接当 OpenAI API 用fromopenaiimportOpenAI clientOpenAI(base_urlhttp://localhost:8000/v1,api_keysk-xxx,# vLLM 不验证 key随便填)responseclient.chat.completions.create(modelmeta-llama/Llama-3.2-3B,messages[{role:user,content:Hello}],)vLLM 关键配置LLM(model...,# 显存配置gpu_memory_utilization0.85-0.95,# 留一些给 CUDA kernelmax_model_len8192,# 最大上下文长度# 性能配置num_scheduler_steps8,# 调度步数越大吞吐越高enable_chunked_prefillTrue,# 分块 prefill降低 TTFT# 量化quantizationawq,# AWQ 量化需要先量化模型# 分布式tensor_parallel_size1,# 1 时需多卡)Step 4性能压测与监控关键指标指标英文含义好值首 Token 延迟TTFT从请求到第一个 Token 的时间 500msToken 生成速度TPOT每个 Token 的生成时间 50ms吞吐量Throughput每秒生成的 Token 数 1000 tokens/s并发数Concurrency同时处理的请求数视场景而定压测工具# 用 vllm 自带的 benchmarkpython-mvllm.benchmarks.benchmark_throughput--modelmeta-llama/Llama-3.2-3B--datasetShareGPT_V3_unfiltered_cleaned_split.json --num-prompts1000# 用 locust 做 HTTP 压测pipinstalllocust locust--hosthttp://localhost:8000生产级部署架构┌─────────────┐ │ Load │ │ Balancer │ └──────┬──────┘ │ ┌───────────────┼───────────────┐ │ │ │ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ │ Worker 1 │ │ Worker 2 │ │ Worker 3 │ │ vLLM/Triton│ │ vLLM/Triton│ │ vLLM/Triton│ └───────────┘ └───────────┘ └───────────┘ │ │ │ ┌─────▼───────────────▼───────────────▼─────┐ │ 共享显存 / 模型分片 │ └───────────────────────────────────────────┘水平扩展多个 Worker 加 Load Balancer动态缩扩容根据队列长度自动调整 Worker 数量缓存层Redis 缓存常见问题的回答适合 LLM 场景回答可以复用总结模型部署的核心链路PyTorch → ONNX → TensorRT → Triton/vLLM → Load Balancer → API ① ② ③ ④ ⑤PyTorch 导出 ONNX设置 dynamic_axesONNX 优化onnxruntime transformersTensorRT 转换FP16 是最优性价比推理框架部署LLM 用 vLLM多模态用 Triton负载均衡与缓存每个环节都有优化空间但先跑通全链路再逐步压测优化是最务实的方式。觉得有用点赞 收藏 关注。