多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

从单模型到LLM推理平台:部署框架设计与vLLM/Triton实战

从单模型到LLM推理平台:部署框架设计与vLLM/Triton实战 1. 从单模型到推理平台部署这件事到底在解决什么问题模型部署这个词听起来像是运维的活儿但真正做过的人都知道它其实是算法、工程、硬件三者的交叉地带。你训练出一个模型准确率再高如果推不出去、跑不起来、扛不住并发那它就只能躺在实验记录里。我见过太多团队在实验室里把指标刷到SOTA一到正式环境就各种翻车——延迟飙高、显存溢出、吞吐量上不去最后不得不降级回退到规则方案。这篇文章想聊的是我自己在正式环境部署模型时踩过的坑和总结出来的框架思路。从最简单的单模型服务到多模型编排再到如今大语言模型LLM的推理平台这条演进路线背后有一套清晰的逻辑。不管你是刚接触部署的算法工程师还是正在搭建推理平台的后端开发或者是需要把模型落地到业务里的技术负责人这些内容应该都能给你一些参考。先说清楚一个基本判断模型部署不是“把模型跑起来”这么简单它是一套围绕延迟、吞吐、成本、稳定性四个维度做权衡的系统工程。单模型服务的时候你只需要关心一个模型的输入输出到了LLM推理平台你要处理的是动态批处理、KV Cache管理、多模型路由、GPU资源调度、弹性扩缩容这一整套问题。复杂度不是线性增长的是指数级的。我自己的经历是从一个图像分类模型的服务化开始的。那时候用Flask包了个接口单进程单GPUQPS个位数觉得部署也就那么回事。后来业务量上来要同时跑检测、分类、分割三个模型还要支持A/B测试和灰度发布才发现之前那套东西根本不够用。再后来接触LLM第一次看到vLLM的PagedAttention论文时才意识到推理优化已经成了一门独立的学问。所以这篇文章的结构是这样安排的先拆解部署框架的整体设计思路讲清楚不同阶段的选型逻辑然后深入核心细节把Triton、vLLM这些工具的关键机制和实操要点讲透接着给出一套完整的实操流程从环境准备到服务上线最后整理常见问题和排查技巧。每一部分都会尽量给出“为什么这么做”的解释而不只是“怎么做”。提示本文涉及的部署方案均基于公开技术文档和社区实践具体参数需要根据你的硬件配置和业务场景做调整不要直接照搬。2. 部署框架的整体设计与选型逻辑2.1 单模型服务阶段的典型架构与局限最早期的模型服务架构简单到可以用一张图说清楚客户端发请求服务端加载模型推理返回结果。这个阶段最常见的技术栈是Flask或FastAPI加PyTorch模型直接加载在进程内存里每次请求走一遍前向传播。这种架构的问题在并发上来之后会集中爆发。首先是Python的GIL限制多线程并不能真正并行执行推理其次是每次请求都要走一遍完整的预处理、推理、后处理流程没有批处理的概念GPU利用率极低再者是模型和代码耦合在一起换模型要改代码重新部署没有版本管理的概念。我当时的做法是用Gunicorn起多个Worker进程每个进程加载一份模型试图用多进程绕过GIL。但这样做的问题是显存占用翻倍一张卡上跑不了几个Worker而且请求分发不均匀有的Worker忙死有的闲死。后来换成Triton Inference Server才算真正解决了这些问题。Triton的核心价值在于它把模型服务和业务逻辑解耦了。你只需要把模型按照规定的目录结构放好写一个配置文件描述输入输出Triton就能自动处理批处理、并发执行、动态加载这些事情。它支持TensorFlow、PyTorch、ONNX、TensorRT等多种后端甚至可以用Python写自定义的推理逻辑。2.2 多模型编排与推理平台的演进当业务需要同时服务多个模型时单模型服务的架构就不够用了。你需要考虑模型路由、版本管理、资源隔离、监控告警这些问题。这时候就需要一个推理平台来统一管理。推理平台的核心组件包括模型仓库存储模型文件和版本、推理引擎执行实际计算、路由层分发请求、调度器管理GPU资源、监控系统采集指标。Triton在这个阶段依然可以用但它更偏向于单机多模型的场景。如果要跨节点调度就需要Kubernetes这样的容器编排系统来配合。我自己的平台选型经历了几次变化。最开始用Triton加Docker Compose管理几个模型还够用。后来模型数量增加到十几个GPU节点也有好几台就换成了Kubernetes加Triton的方案。Kubernetes负责Pod调度和弹性扩缩容Triton负责单节点内的模型管理和推理执行。这个组合的优点是生态成熟、社区活跃缺点是学习曲线陡峭运维复杂度高。到了LLM时代推理平台的需求又变了。LLM的推理和传统模型有本质区别它是自回归生成每次输出一个token需要反复调用模型它的显存占用极大KV Cache可能比模型本身还大它的请求长度差异悬殊短的几十个token长的几万个token。这些特点决定了传统的批处理策略在LLM场景下效果很差。vLLM就是为解决这些问题而生的。它的核心创新是PagedAttention把KV Cache分成固定大小的块来管理就像操作系统的虚拟内存分页一样。这样做的好处是显存利用率大幅提升因为不再需要为每个请求预留最大长度的连续显存空间。配合连续批处理Continuous BatchingvLLM可以在一个批次里同时处理不同阶段的请求吞吐量比朴素实现高出数倍。2.3 选型决策的关键维度与对比面对Triton、vLLM、Ollama、SGLang这些工具怎么选我一般从以下几个维度来评估维度TritonvLLMOllamaSGLang主要场景传统模型多模型服务LLM高吞吐推理本地LLM快速体验LLM结构化生成批处理动态批处理连续批处理PagedAttention有限支持RadixAttention多模型原生支持单模型为主多模型切换单模型为主部署复杂度中等中等低中等硬件要求GPU为主GPU为主CPU/GPU均可GPU为主生态成熟度高高高中选型的核心原则是匹配你的主要矛盾。如果你要服务的是BERT、ResNet这类传统模型Triton是最稳妥的选择如果你要部署LLM并且追求高吞吐vLLM是当前社区的主流方案如果你只是想在本地快速跑一个模型做demoOllama的体验最好如果你需要做结构化输出或者复杂的生成控制SGLang的RadixAttention和DSL可能更合适。还有一个容易被忽略的点是模型格式。传统模型常用ONNX、TensorRT、TorchScript这些格式LLM则多用HuggingFace Transformers格式或GGUF格式。GGUF是llama.cpp推出的量化格式适合在CPU或低显存GPU上运行但吞吐量不如vLLM。ONNX Runtime在传统模型上性能很好但对LLM的支持还在完善中。3. 核心细节解析与实操要点3.1 Triton Inference Server的模型仓库与配置Triton的模型仓库结构是有严格规定的。每个模型一个目录目录名就是模型名里面放版本号命名的子目录每个版本目录里放模型文件和配置文件。model_repository/ ├── text_classification/ │ ├── 1/ │ │ ├── model.py │ │ └── config.pbtxt │ └── config.pbtxt └── image_encoder/ ├── 1/ │ └── model.onnx └── config.pbtxtconfig.pbtxt是Triton的核心配置文件它定义了模型的输入输出、批处理策略、实例数量等关键参数。我见过很多人在这里踩坑最常见的问题是输入输出的维度写错导致Triton无法正确分配显存。name: text_classification platform: python max_batch_size: 32 input [ { name: INPUT_TEXT data_type: TYPE_STRING dims: [ -1 ] } ] output [ { name: OUTPUT_SCORE data_type: TYPE_FP32 dims: [ 2 ] } ] instance_group [ { count: 2 kind: KIND_GPU gpus: [ 0 ] } ] dynamic_batching { preferred_batch_size: [ 8, 16, 32 ] max_queue_delay_microseconds: 100000 }max_batch_size决定了Triton能合并的最大请求数。这个值不是越大越好因为批处理会增加单次推理的延迟。我的经验是对于延迟敏感的场景max_batch_size设在8到16之间对于吞吐优先的场景可以设到32甚至64。max_queue_delay_microseconds是等待批处理凑齐的最长时间设得太大会增加延迟设得太小会导致批处理效率低。100毫秒是一个比较平衡的值。instance_group里的count决定了每个GPU上启动几个模型实例。多实例可以提高并发能力但会占用更多显存。如果模型本身不大显存充足可以设2到4个实例如果模型很大显存紧张就设1个。注意Triton的Python后端虽然灵活但性能不如C后端。如果模型可以导出为ONNX或TensorRT优先用这些后端。Python后端适合做预处理后处理逻辑复杂的场景。3.2 vLLM的PagedAttention与连续批处理机制vLLM的性能优势主要来自两个机制PagedAttention和连续批处理。理解这两个机制对于调优和排查问题非常重要。PagedAttention的核心思想是把KV Cache分成固定大小的块Block每个块存储固定数量token的Key和Value向量。不同请求的块可以存储在非连续的显存空间里通过块表Block Table来映射逻辑位置和物理位置。这样做的好处是消除了显存碎片因为不需要为每个请求预留最大长度的连续空间。举个例子假设一个请求的最大生成长度是2048个token但实际只生成了100个token。朴素实现会为这个请求预留2048个token的KV Cache空间浪费了95%的显存。PagedAttention只分配实际需要的块100个token可能只占2到3个块显存利用率大幅提升。连续批处理解决的是另一个问题。传统批处理是静态的一个批次里的所有请求必须同时开始、同时结束。如果批次里有一个请求生成了1000个token另一个只生成了10个token那短请求必须等长请求完成才能释放资源。连续批处理允许在一个批次里动态加入新请求、移除已完成请求GPU始终处于满负荷状态。vLLM的部署命令很简洁python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --tensor-parallel-size 2 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --max-num-seqs 256 \ --port 8000tensor-parallel-size是张量并行的GPU数量需要根据模型大小和GPU数量来设置。7B模型用2张卡做张量并行比较合适70B模型可能需要4到8张卡。max-model-len是最大序列长度这个值直接影响KV Cache的显存占用设得越大显存需求越高。gpu-memory-utilization是显存利用率上限0.9表示使用90%的显存留10%给系统和其他进程。max-num-seqs是最大并发序列数这个值决定了连续批处理的批次大小上限。我实测下来Qwen2.5-7B-Instruct在2张A100 80G上max-model-len设为8192gpu-memory-utilization设为0.9可以支持大约200个并发请求吞吐量在3000 tokens/s左右。如果max-model-len降到4096并发数可以翻倍吞吐量也能提升30%左右。3.3 模型量化与显存优化的实操细节显存是LLM部署中最稀缺的资源。除了PagedAttention量化是另一个重要的优化手段。常见的量化方案有GPTQ、AWQ、GGUF、FP8等。GPTQ和AWQ是训练后量化PTQ方法把模型权重从FP16压缩到INT4显存占用降到原来的四分之一左右。GPTQ的量化粒度更细精度损失更小AWQ对激活值做保护在某些任务上表现更好。我一般优先用AWQ因为它在推理时的速度略快于GPTQ。GGUF是llama.cpp的格式支持CPU和GPU混合推理。它的优势是可以在显存不足时把部分层放到CPU上缺点是推理速度慢。如果GPU显存足够不建议用GGUF。FP8是H100等新卡支持的原生格式精度损失比INT4小速度比FP16快。但FP8需要硬件支持老卡用不了。量化的实操命令以AWQ为例python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct-AWQ \ --quantization awq \ --dtype float16 \ --tensor-parallel-size 1 \ --max-model-len 8192 \ --gpu-memory-utilization 0.85注意--quantization awq这个参数必须加上否则vLLM会按FP16加载量化就白做了。--dtype float16指定计算时的数据类型量化模型的计算通常还是用FP16。提示量化会带来一定的精度损失部署前一定要在你的业务数据上做评估。我见过量化后准确率掉5个百分点的案例这种就不能接受。一般来说INT4量化在7B以上的模型上精度损失在1到2个百分点以内是可以接受的。4. 完整实操流程从环境准备到服务上线4.1 环境准备与依赖安装正式环境部署的第一步是环境准备。我习惯用Docker来管理环境因为这样可以保证开发、测试、生产环境的一致性。以vLLM为例官方提供了预构建的镜像docker pull vllm/vllm-openai:latest如果需要特定版本可以指定tag比如vllm/vllm-openai:v0.6.3。我建议在生产环境使用固定版本不要用latest因为latest可能随时更新引入不可预期的变化。启动容器的命令docker run --runtime nvidia --gpus all \ -v ~/.cache/huggingface:/root/.cache/huggingface \ -p 8000:8000 \ --ipchost \ vllm/vllm-openai:v0.6.3 \ --model Qwen/Qwen2.5-7B-Instruct \ --tensor-parallel-size 2 \ --max-model-len 8192--runtime nvidia和--gpus all是让容器能访问GPU。--ipchost是共享主机内存vLLM在多进程通信时需要这个。-v把HuggingFace的缓存目录挂载到容器里这样模型下载一次就够了不用每次启动都重新下载。如果不用Docker直接pip安装也可以pip install vllm0.6.3但要注意CUDA版本和PyTorch版本的兼容性。vLLM 0.6.3需要PyTorch 2.4以上CUDA 12.1以上。版本不匹配会导致各种奇怪的错误比如kernel编译失败、显存分配异常等。4.2 模型下载与格式转换模型下载有两种方式直接从HuggingFace Hub拉取或者手动下载后放到本地目录。直接拉取最简单from huggingface_hub import snapshot_download snapshot_download( repo_idQwen/Qwen2.5-7B-Instruct, local_dir./models/Qwen2.5-7B-Instruct, local_dir_use_symlinksFalse )如果网络不稳定可以用hf_transfer加速pip install hf_transfer export HF_HUB_ENABLE_HF_TRANSFER1格式转换主要针对量化模型。如果你有一个FP16的模型想转成AWQ格式可以用AutoAWQfrom awq import AutoAWQForCausalLM from transformers import AutoTokenizer model_path Qwen/Qwen2.5-7B-Instruct quant_path Qwen2.5-7B-Instruct-AWQ model AutoAWQForCausalLM.from_pretrained(model_path) tokenizer AutoTokenizer.from_pretrained(model_path) quant_config {zero_point: True, q_group_size: 128, w_bit: 4, version: GEMM} model.quantize(tokenizer, quant_configquant_config) model.save_quantized(quant_path) tokenizer.save_pretrained(quant_path)q_group_size是量化分组大小128是常用值。w_bit是量化位数4表示INT4。version是量化算法版本GEMM是通用矩阵乘法版本兼容性最好。4.3 服务启动与接口测试服务启动后vLLM会暴露一个兼容OpenAI API的接口。测试命令curl http://localhost:8000/v1/completions \ -H Content-Type: application/json \ -d { model: Qwen/Qwen2.5-7B-Instruct, prompt: 请用一句话解释什么是模型部署, max_tokens: 100, temperature: 0.7 }如果返回正常说明服务已经跑起来了。接下来要做压力测试看看在实际负载下的表现。我一般用locust或wrk来做压测。wrk -t4 -c100 -d30s --latency -s post.lua http://localhost:8000/v1/completionspost.lua是自定义的压测脚本构造请求体。-t4是4个线程-c100是100个并发连接-d30s是持续30秒。压测时要关注几个指标首token延迟TTFT、每token延迟TPOT、吞吐量tokens/s、GPU利用率、显存占用。TTFT反映的是预填充阶段的性能TPOT反映的是解码阶段的性能。如果TTFT高说明预填充计算量大可以考虑增加张量并行度如果TPOT高说明解码效率低可以检查KV Cache的块大小是否合理。4.4 监控告警与日志采集正式环境必须有监控。vLLM暴露了Prometheus格式的指标可以直接接入Prometheus加Grafana的监控体系。curl http://localhost:8000/metrics关键指标包括vllm:num_requests_running正在处理的请求数、vllm:num_requests_waiting等待队列长度、vllm:gpu_cache_usage_percKV Cache使用率、vllm:avg_prompt_throughput预填充吞吐、vllm:avg_generation_throughput解码吞吐。我一般会设置几个告警规则等待队列长度超过50持续1分钟说明容量不足需要扩容KV Cache使用率超过95%持续5分钟说明显存快满了可能需要降低max-model-len或增加GPUTTFT的P99超过2秒说明预填充阶段有瓶颈。日志采集用ELK或Loki都可以。vLLM的日志默认输出到stdoutDocker环境下可以用docker logs查看Kubernetes环境下用kubectl logs。我习惯把日志收集到Loki然后在Grafana里和指标一起看排查问题时可以对照时间线。5. 常见问题与排查技巧实录5.1 显存溢出与OOM的排查路径显存溢出是LLM部署中最常见的问题。报错信息通常是CUDA out of memory但原因可能有很多种。第一步是确认显存被什么占用了。用nvidia-smi看整体显存占用用torch.cuda.memory_summary()看PyTorch的显存分配情况。如果模型加载后就OOM说明模型本身太大需要量化或增加GPU。如果运行一段时间后OOM说明KV Cache增长超出了预期需要降低max-model-len或max-num-seqs。我遇到过一个案例模型加载正常但一有请求就OOM。排查后发现是gpu-memory-utilization设成了0.95留给KV Cache的空间太小第一个请求的预填充就撑爆了。改成0.85后问题解决。还有一个隐蔽的坑是显存碎片。即使总显存够用如果碎片太多也可能分配失败。vLLM的PagedAttention本身就是为了解决碎片问题但如果用了其他推理框架可能需要手动调用torch.cuda.empty_cache()来整理碎片。现象可能原因排查方法解决方案加载模型时OOM模型太大检查模型参数量和精度量化或增加GPU首个请求OOMKV Cache预留不足检查gpu-memory-utilization降低该值到0.8-0.85运行中OOM并发过高检查num_requests_running降低max-num-seqs随机OOM显存碎片检查显存分配日志重启服务或换PagedAttention方案5.2 推理延迟波动的归因分析延迟波动是另一个让人头疼的问题。同样的请求有时候100毫秒返回有时候要2秒。这种波动通常来自几个方面。首先是批处理的影响。连续批处理虽然提高了吞吐但也会让单个请求的延迟变得不确定。如果一个请求被分到了一个很大的批次里它的解码速度就会变慢。这是吞吐和延迟的固有权衡没有完美的解决方案。如果业务对延迟极其敏感可以考虑关闭连续批处理或者设置更小的max-num-seqs。其次是KV Cache的换入换出。当显存不足时vLLM会把部分KV Cache换到CPU内存需要时再换回来。这个换入换出的过程会带来毫秒级的延迟。如果观察到周期性的延迟尖峰可以检查gpu_cache_usage_perc是否接近100%。还有一个容易被忽略的因素是GPU频率。有些云厂商的GPU实例默认是节能模式频率会根据负载动态调整。在高负载时频率上不去导致推理变慢。可以用nvidia-smi -q -d CLOCK查看当前频率用nvidia-smi -lgc锁定频率。提示延迟优化没有银弹必须结合业务场景做权衡。我的经验是先保证P99延迟可接受再优化吞吐。如果反过来很容易陷入“吞吐上去了但用户体验崩了”的困境。5.3 模型加载失败的典型原因模型加载失败的原因五花八门我整理了几个最常见的配置文件缺失或格式错误。HuggingFace模型目录下必须有config.json、tokenizer.json、tokenizer_config.json这些文件。如果是从其他地方拷贝的模型很容易漏掉某个文件。用snapshot_download下载可以避免这个问题。权重文件损坏。下载过程中断可能导致.safetensors文件不完整。可以用safetensors库的校验功能检查from safetensors import safe_open with safe_open(model.safetensors, frameworkpt) as f: for key in f.keys(): tensor f.get_tensor(key) print(key, tensor.shape)版本不兼容。vLLM的版本和模型架构的版本要匹配。比如Qwen2.5需要vLLM 0.6.0以上Qwen2需要vLLM 0.5.0以上。用太老的vLLM加载新模型会报KeyError或AttributeError。自定义模型代码缺失。有些模型需要trust_remote_codeTrue因为它们的架构定义在模型仓库的Python文件里不在Transformers库里。如果忘了加这个参数会报Model type not recognized。5.4 并发性能调优的实操经验并发性能调优是一个反复迭代的过程。我的做法是先用默认参数跑一遍基准测试然后逐个调整参数观察指标变化。第一步是确定max-num-seqs。这个值决定了同时处理的最大请求数。设得太小GPU利用率上不去设得太大延迟会飙升。我一般从128开始逐步增加到256、512观察吞吐量和延迟的变化。当吞吐量不再增长而延迟明显上升时就是拐点。第二步是调整max-model-len。这个值直接影响KV Cache的显存占用。如果业务请求的平均长度是1000个tokenP99长度是4000个token那max-model-len设4096就够了没必要设8192。每降低一半KV Cache的显存占用就降低一半可以支持更多的并发。第三步是考虑张量并行。张量并行可以把模型切分到多张GPU上降低单卡的显存压力但会增加通信开销。2卡张量并行的通信开销大约在10%到20%之间4卡会更高。如果单卡显存够用不建议用张量并行。第四步是考虑流水线并行。流水线并行把模型的不同层放到不同GPU上通信开销比张量并行小但会有流水线气泡。对于LLM推理流水线并行的效果通常不如张量并行。我实测的一组数据Qwen2.5-7B-Instruct2张A100 80Gmax-model-len4096gpu-memory-utilization0.9max-num-seqs从128增加到512时吞吐量从2200 tokens/s提升到3800 tokens/s但P99 TTFT从800毫秒增加到2.3秒。最终我选择了256作为平衡点吞吐量3200 tokens/sP99 TTFT 1.2秒。6. 从单模型到LLM推理平台的架构演进思考6.1 传统模型与LLM部署的架构差异传统模型部署和LLM部署在架构上有本质区别。传统模型是“一次推理一次输出”输入一张图或一段文本输出一个结果请求之间相互独立。LLM是“自回归生成”输入一个prompt输出一个token序列每个token的生成都依赖于之前的token。这个差异导致了两者在批处理策略上的根本不同。传统模型的批处理是静态的一个批次里的请求同时开始同时结束。LLM的批处理必须是动态的因为不同请求的生成长度差异很大。vLLM的连续批处理就是为此设计的。另一个差异是显存管理。传统模型的显存占用是固定的模型加载后显存就确定了。LLM的显存占用是动态的KV Cache随着生成长度增长。PagedAttention通过分页管理解决了这个问题。还有一个差异是服务接口。传统模型通常用gRPC或HTTP的简单接口输入输出是固定维度的张量。LLM用流式接口输出是逐个token返回的。这对服务端的并发处理能力提出了更高要求。6.2 多模型路由与版本管理的实现当平台上有多个模型时路由和版本管理就变得重要了。路由层需要根据请求中的模型标识把请求分发到对应的推理服务。版本管理需要支持灰度发布和回滚。我自己的做法是用一个轻量级的网关来做路由。网关维护一个模型到服务地址的映射表请求进来后查表转发。映射表可以动态更新支持热加载。class ModelRouter: def __init__(self): self.routes {} def register(self, model_name, version, endpoint): key f{model_name}:{version} self.routes[key] endpoint def route(self, model_name, versionNone): if version: key f{model_name}:{version} return self.routes.get(key) else: candidates [k for k in self.routes if k.startswith(f{model_name}:)] if candidates: latest sorted(candidates)[-1] return self.routes[latest] return None灰度发布可以通过权重路由来实现。比如新版本上线时先给10%的流量观察指标正常后再逐步增加。6.3 弹性扩缩容与成本控制弹性扩缩容是推理平台的重要能力。业务量有高峰有低谷如果一直保持最大容量成本会很高。Kubernetes的HPA可以根据CPU或自定义指标来扩缩容。对于LLM推理CPU利用率不是一个好的扩缩容指标因为瓶颈在GPU。更好的指标是等待队列长度或KV Cache使用率。可以用Prometheus Adapter把这些指标暴露给HPA。apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: vllm-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: vllm-deployment minReplicas: 1 maxReplicas: 4 metrics: - type: Pods pods: metric: name: vllm_num_requests_waiting target: type: AverageValue averageValue: 10这个配置的意思是当等待队列的平均长度超过10时自动扩容最多扩到4个副本。缩容的阈值可以设得低一些比如等待队列为0持续5分钟就缩容。成本控制还有一个手段是混合部署。把延迟不敏感的离线任务和在线服务混部在同一批GPU上离线任务在在线服务低谷时占用资源高峰时让出资源。这需要更复杂的调度策略但可以显著提高GPU利用率。6.4 未来演进方向与个人判断从单模型服务到LLM推理平台这条路我走了大概三年。回头看最大的感受是部署框架的演进方向是越来越“重”。早期的Flask加PyTorch几百行代码就能跑起来现在的推理平台涉及容器编排、服务网格、监控告警、自动扩缩容复杂度高了不止一个量级。但这个“重”是有价值的。当业务规模上来之后没有这套基础设施根本撑不住。我见过太多团队在业务量增长后被迫重构部署架构代价很大。如果一开始就按照平台的思路来设计虽然前期投入大一些但后期扩展会顺畅很多。对于未来我个人比较关注几个方向一是推理和训练的融合比如用同一个集群既做训练又做推理提高资源利用率二是异构硬件的支持除了GPU还有NPU、TPU等各种加速器如何统一调度是个问题三是自动调优根据业务负载自动调整批处理大小、并发数这些参数减少人工调参的成本。这些方向目前都还在演进中没有成熟的方案。但有一点是确定的模型部署会越来越像一个独立的工程领域需要专门的知识和技能。如果你正在这个领域建议多动手实践多踩坑多总结。文档和论文能给你方向但真正的经验只能从实操中来。最后分享一个我自己的小习惯每次部署新模型时我都会记录一份“部署日志”包括硬件配置、软件版本、关键参数、压测数据、遇到的问题和解决方案。这份日志在后续排查问题和优化性能时非常有用也方便团队其他成员参考。踩过的坑不白踩记录下来就是经验。
返回列表