新闻详情

新闻详情

首页 / 资讯中心 / 详情

vLLM重构GPU抽象层:从CUDA绑定到多硬件可移植的架构演进

发布时间:2026/10/1 6:06:27来源:尧图网络
vLLM重构GPU抽象层:从CUDA绑定到多硬件可移植的架构演进
1. 先搞明白vLLM为什么绕不开GPU抽象这回事vLLM这个名字里的V原意是Virtual最早走红是因为两个杀手级特性PagedAttention和Continuous Batching。一个把操作系统虚拟内存换页的思路搬到了KV Cache管理上把显存利用率拉满另一个让请求像流水线一样持续进出GPU把GPU利用率托到一个很夸张的水平。这两个特性让vLLM几乎成为了大模型推理服务的事实标准但也埋下了一个必须面对的隐患——vLLM的整个调度逻辑从一开始就深度绑定在CUDA平台上。先说清楚vLLM日常在GPU上到底干什么。拆开来看无非三件事显存管理KV Cache要预留、要分配、要换页、要释放中间激活值也要临时存储。显存管不好模型根本跑不起来或者跑起来了也极不稳定。算子执行Attention、LayerNorm、GeLU这些数学运算全部要落成GPU kernel。算子效率基本决定了推理速度的上限。调度与排队请求什么时候进GPU、什么时候出GPUbatch怎么拼prefill和decode阶段怎么平衡这些逻辑在CPU侧完成但直接影响GPU利用率。所以vLLM本质上是一个极其复杂的CPU侧调度 GPU侧执行系统。CPU侧是Python和C混编的控制流GPU侧是大量CUDA kernel。过去很长一段时间NVIDIA GPU是绝对的主流CUDA生态又太成熟vLLM只需要在CUDA层之上把调度逻辑写好就行了一切都顺理成章。那问题出在哪出在vLLM的野心不止于NVIDIA GPU。如果你关注过ChatBot Arena和各大推理厂商的部署清单你会看到AMD MI300系列、Intel Gaudi系列、华为昇腾系列在推理场景下越来越常见。国内云厂商的部署矩阵里昇腾的占比逐年上升。每个平台都有自己的SDK、自己的kernel语言、自己的显存管理方式。如果vLLM的核心调度逻辑绑死CUDA API那每一个新平台都要把这套调度逻辑重写一遍。这还只是GPU层面的变化。更远的池子里还有Groq的LPU、Cerebras的WSE以及各种NPU、DPU也在大模型推理里被反复尝试。这些设备连CUDA都不用kernel模型都完全不同。Groq那套是显式流式执行根本没有thread/block/grid这回事。所以vLLM为了新GPU拆掉旧的抽象本质上是架构演进到了非做不可的节点。这篇文章我会从几个维度深聊这件事为什么要拆旧抽象为什么要再造一层可移植层这一层到底应该承载什么以及实际落地时有哪些经验教训。2. 为什么要拆掉旧抽象四个不可回避的原因我先把拆旧抽象的动机捋一遍。这里面有四层原因一层比一层硬核。理解了这四个层次你基本就明白vLLM团队在做这个决策时到底看到了什么。2.1 硬件形态的爆发式增长旧抽象根本兜不住先说最直观的原因GPU之外的加速器形态太多了。非NVIDIA显卡全面崛起这件事这两年已经非常明显。AMD的ROCm生态逐步成熟Intel的Gaudi在整个推理市场里有一席之地昇腾在国内的供给量非常大。每个平台都有自己的SDK、自己的kernel语言、自己的显存管理方式。如果核心调度逻辑绑死CUDA API移植到新平台的工作量是灾难级的。更远的池子里还有Groq的LPU、Cerebras的WSE这些完全不走GPU路线的加速器。它们连CUDA都不认kernel模型都不一样。Groq那套是显式流式执行不能套用GPU上的block/thread模型。vLLM要往前发展必须把设备无关和设备相关两个层面分开。还有一个非常实际的点多GPU、多节点的形态已经是标配。显存不够用早就成了常态张量并行、流水线并行、多节点推理都成了基本操作。vLLM需要在一套抽象里支持跨设备、跨节点的显存和kernel管理。而旧的抽象骨子里是为单进程单GPU设计的。这个设计前提在今天的语境下已经很不牢靠了。2.2 CUDA太直了暴露了细节也绑架了逻辑CUDA这套东西用下来的感觉是直接、高效但也很粗糙。它给你一个设备指针让你自己管理显存分配给你一个kernel索引空间让你自己布局线程你在全局内存和共享内存之间倒数据完全手动。vLLM的调度器要做得复杂就必须知道当前显存里到底有哪些块、哪些块还能用。在CUDA之下这个信息得自己维护。PagedAttention能够生效就是因为vLLM自己把KV Cache切成了固定大小的物理块然后手动管理映射关系。这种手动管理一切的方式在NVIDIA单一平台上没有任何问题因为你的代码可以深度绑定CUDA的细节。但问题恰恰在于细节一旦绑死换平台就完蛋。vLLM的调度逻辑本身并不关心显存块在第几号GPU上、通过什么总线访问它真正关心的是给我一片显存区域我要往里面写KV数据。这个不关心的地方才是抽象应该存在的地方。CUDA的问题是它把所有细节都暴露给你了然后你的注意力就被这些细节牵走了。2.3 社区维护成本失控一个PR要在五个后端里改五遍vLLM是一个迭代速度极快的开源项目。v0.6.x到v0.7.x之间几乎每一两周就有一个release。功能上不停加新模型、新量化方式、新并行策略。如果一个项目要在五个硬件平台上各维护一套和CUDA平台等价的代码那一个PR进来要在五个后端同时改。这个维护成本不是线性增长是平方级增长。还有一个人力层面的现实社区里能给AMD、Intel、昇腾写kernel的人远少于能给NVIDIA写kernel的人。如果抽象层不做隔离新的硬件贡献者连门都找不到。做了抽象层之后新硬件厂商只需要面对一个定义清晰的接口面把该实现的方法实现掉vLLM就能跑起来。这对开源社区的价值是非常直接的。2.4 更长期的架构演进vLLM想成为大模型推理的LinuxvLLM最近在做一件大事就是把执行器executor做模块化。未来大概率会形成一种架构让核心调度逻辑成为一层完全设备无关的库让GPU相关的部分变成插件式的后端。这种架构最理想的状态是新硬件厂商只要实现一套后端接口就能无缝接入整个vLLM生态。打个比方这就像Linux的设备驱动模型——核心内核不直接操作硬件而是通过驱动框架去沟通。硬件厂商写好驱动内核就认得这块硬件。vLLM想象自己未来的归宿就是Linux这个形态。所以拆旧抽象的根本原因不是团队闲得慌而是架构演进到这一步已经不能再拖了。与其在后面到处都是补丁的时候拆不如在结构还相对健康的时候动手。3. 为什么拆了旧抽象之后还要再造一个可移植层拆掉旧抽象这件事做完之后紧接着就是一个更难的命题拆掉的东西总得有东西补上。如果补上的东西只是一堆裸接口那局面只会更乱。3.1 用一个反例说明裸接口方案为什么只有死路一条有人可能会说那干脆就别搞抽象层了。核心逻辑直接调用每个平台的原生API哪个平台来了就写哪份逻辑。能跑就行为什么要多一层短期行长期一定不行。裸接口意味着每个平台都单独调自己的API。看起来少了一层实则每次跨平台移植都是重写。更深刻的问题是调度的语义——比如分配一个KV Cache块执行一个Attention kernel同步一批设备状态——在不同平台下的API差异巨大你没法用一套逻辑去统一表达。最关键的还是性能不能丢。抽象层存在的原因是让你屏蔽掉各平台底层细节之后还能保持性能。如果为了统一而把所有显存分配都变成通用malloc那就回到了性能灾难的老路上去了。裸接口方案就是不设防的公路看起来哪都能去但一上高速就散架。3.2 这一层到底要解决什么问题三个核心点那我把它拆成三个核心问题讲每个都很硬。第一个核心问题KV Cache的显存管理要可移植。在NVIDIA平台上vLLM把整个显存看成一个线性地址空间划成等大小的物理块。在AMD平台上显存管理接口很像CUDA但又不完全一样。在昇腾上显存是通过ACL接口来管理的。问题是调度器需要的是这块显存区域我可以写数据写完之后数据还在。这个语义在所有平台上都是成立的。所以可移植层要做的就是把不同平台的显存分配、释放、同步操作统一成分配一个KV Cache块这样的高层接口。底层细节平台自己实现。第二个核心问题kernel执行要可移植。调度器需要的是把这个kernel在GPU上跑起来跑完告诉我结果而不是往CUDA stream里挂一个kernel。所以可移植层要设计一个kernel发布和执行的接口。麻烦的是不同平台的kernel模型完全不同。NVIDIA是thread/block/grid三层模型AMD大体相似Intel也有类似的分组模型但昇腾是Tiling加Vector/Matrix单元化计算的模型Groq更是流式执行。这层抽象不能把某一种平台的执行模型当成唯一标准否则就是在造一个更大的CUDA模拟器那样的话还不如不拆。第三个核心问题设备生命周期管理要可移植。设备初始化、上下文创建、流管理、同步、设备间拷贝在CUDA里是一套完整的API。换平台就全变了。可移植层需要把这套能力抽象成设备上下文这个概念。调度器只跟设备上下文打交道不关心底层到底是CUDA还是hip还是ascend还是别的什么。3.3 容易忽略的点权限边界管理可移植层最怕的就是接口太细导致各个平台又用各自的方式绕过抽象层、直接操作硬件。这一层设计时一定要定清楚哪些功能必须通过接口完成哪些功能允许平台侧自行优化。我的建议是多层防线核心调度逻辑严格只调用抽象接口不允许出现平台相关代码。平台接入层允许用原生API但必须实现统一的接口面。凡是侵入核心逻辑的特殊优化必须通过扩展点来做不能直接改核心代码。这层表面上看是规矩实际上是可移植层能不能长期活下去的关键。如果边界不清晰半年后你就会发现核心代码里散落着各种平台的if else那还不如当初不拆。4. 实操中如何设计这层可移植层前面讲了那么多概念这节直接落到代码和设计思路层面结合vLLM的现有代码结构来谈。我不是vLLM团队的人但以我自己做过多平台推理适配的经验来说很多设计原则是通用的。4.1 从vLLM现有代码结构看抽象层的位置vLLM的代码结构大致划分成下面几块vllm/ core/ # 核心调度逻辑设备无关 engine/ # 推理引擎设备相关但偏向控制流 model_executor/ # 模型加载和并行执行设备相关 worker/ # 设备侧worker真正调用kernel的地方 platform/ # 平台抽象层后加关键点在于core和platform之间要有一条非常清晰的线。核心调度只依赖抽象接口而platform层真正调底层SDK。我自己设计类似系统时习惯定这样一条依赖规则依赖方向只能从core指向platform不能反过来。platform接口面必须足够小——理想情况是10到20个方法级接口而不是几百个。所有设备相关的数据结构在core层必须表现为不透明的句柄不允许直接操作。这三点缺一不可。依赖方向错误的话核心逻辑慢慢就会被平台细节污染接口面太宽的话抽象层就形同虚设句柄不透明的话大家就会忍不住往里钻。4.2 给一个浅显的接口设计示例假设我们要抽象一个分配KV Cache块的操作。不同平台的实现完全不同但接口应该只有一两个方法。示意代码如下这不是vLLM源码但思路和vLLM的抽象思路一致class PlatformBackend(ABC): abstractmethod def allocate_kv_cache_block(self, logical_size: int) - BlockHandle: 在设备上申请一块物理显存区域用于存放KV Cache。 返回一个不透明的句柄核心层不能解析它的内部结构。 abstractmethod def free_kv_cache_block(self, handle: BlockHandle) - None: 释放之前申请的显存块。 abstractmethod def launch_kernel(self, kernel: KernelSpec, args: list) - None: 在默认流上启动一个kernel。KernelSpec 携带 kernel 名称、 grid/block 维度、共享内存大小等元数据。 核心层永远只通过launch_kernel去执行计算不关心kernel底层是CUDA的cuLaunchKernel还是昇腾的aclrtlaunch。这个封装的价值不在代码量而在把什么计算和怎么执行彻底分开。4.3 KernelSpec的设计一个非常细节但极重要的话题有挑战的一个问题是kernel的发布形式各平台差异巨大。NVIDIA用PTX或者CUBINAMD用HSA Code ObjectIntel用SPIR-V昇腾用.om模型文件。你没法统一成一种格式。所以KernelSpec必须允许平台侧在launch_kernel内部自行解析。核心层只传一个kernel_id平台侧维护一个kernel_id - 平台可执行文件的映射。class KernelSpec: 一个设备无关的kernel描述。 核心层只关心kernel的语义ID和参数平台侧负责将ID映射为 当前平台的可执行kernel并解析所有平台相关的布局参数。 kernel_id: str # e.g. attention_forward_plain block_sizes: tuple # 统一语义下的逻辑块大小不是CUDA block num_warps: int # 逻辑意义上的warp数平台侧自行映射 shared_mem_bytes: int # 需要的共享内存/片上内存量这层设计的几点经验KernelSpec本身不要携带太多平台细节否则又变成了统一平台。平台侧要有自己的kernel cache不要每次启动都去加载文件。关键kernel比如Attention允许前端传入优化参数比如tile size、block size但参数含义要在最高层定义清楚不能是CUDA特有的。4.4 显存管理的抽象实践显存管理这块我觉得是抽象层里最容易被写坏、但又最关键的部分。原因在于显存管理不只是分配释放还涉及Cache的换入换出、多设备间数据搬移、虚拟内存映射。这些操作在CUDA里太顺手了大家都习惯直接干。抽象时至少要做到这几点显存分配只按块block为单位不暴露底层的字节级接口。KV Cache换入换出要设计明确接口每个平台实现自己的策略。设备间拷贝做成一个方法平台侧负责选择最优路径。允许平台侧提供自定义显存布局比如有的平台可能希望把KV Cache块放到非连续地址空间这在抽象层应该是允许的。很多人在设计这层时容易走极端做得太抽象性能全丢做得太细平台差异没法容纳。先做块级抽象再逐步下钻到字节级是更稳的路线。先保证调度逻辑的正确性和稳定性再针对每个平台逐个优化底层。5. 可移植层带来的实际收益这层设计好了之后不是给架构师看的概念而是有实实在在收益的。5.1 新硬件接入成本大幅降低以前要接入一个新GPU平台你需要理解vLLM的全部调度逻辑然后在各处改代码。有了可移植层之后你只需要四件事实现PlatformBackend的全部方法。提供每个模型的kernel映射。维护显存管理实现。写几组冒烟测试。只要这四步走完哪怕你完全不懂调度逻辑也能把vLLM跑起来。这个收益对开源项目是巨大的因为它意味着更多的贡献者、更多的测试矩阵、更快的迭代速度。5.2 性能可以下沉到平台侧可移植层不是把所有平台的性能都拉平恰恰相反它让每个平台都能把性能压榨到极致。因为在核心逻辑不做平台分支的情况下平台后端自己拥有一整块可以自由优化的空间。NVIDIA可以用更精细的PagedAttention策略AMD可以用更积极的显存复用昇腾可以用矩阵单元最擅长的tiling策略。底层平台的优化不会再去破坏核心调度逻辑因为它们的修改全局限在自己的后端里。这其实是越抽象越高效的典型例子——听起来反直觉但确实是现实中验证过的结果。5.3 测试和维护变得可预期一个健壮的可移植层加上明确的平台划分意味着测试矩阵可以雨后春笋一样扩展开。你可以为每个平台跑独立的集成测试、性能回归测试。只要抽象层的接口在核心逻辑就能稳定测试。我自己实测下来的感受是抽象层设计得好不好最后全在维护体验上体现。好的抽象层改一个平台无关的bug你只需要改核心代码改一个平台相关的bug你只需要改该平台的backend。两边互不干扰效率和安全感都高很多。6. 常见坑与避坑经验最后分享几个我实际踩过的、或者见过别人踩的坑希望你能绕开。6.1 坑一接口必须保持最小最先踩的坑一定是接口面失控。很多人觉得抽象层要覆盖完整于是一口气设计七八十个接口恨不得把CUDA的cudaMalloc、cudaFree、cudaMemcpy全变成抽象方法。结果是接口越多核心逻辑越容易依赖细节抽象层的价值反而越小。我的建议是接口面控制在20个以内并且做好优先级排序。先做保证正确性的接口再做保证性能的接口最后才做扩展点。永远不要为了完整而牺牲精简。6.2 坑二性能不可回退抽象层最容易被挑战的就是性能去哪了。每次加一层抽象一定会引入一点性能损耗。关键在于把损耗控制在可观测、可接受的范围内。我的做法是在核心调度里引入几个性能探针专门测量经过抽象层的调用耗时然后定期做性能回归。如果发现某个调用在特定平台上异常变慢就有据可查。6.3 坑三不要让抽象层变成又一个CUDA模拟器这是最隐蔽的坑。设计抽象层时设计者脑子里往往还是CUDA的模型于是抽象出来的接口本质上就是CUDA API换了个名字。这样做的结果是其他平台为了保证兼容只能去模拟CUDA的行为性能肯定拉垮。正确的姿势是抽象这一层时不要绑定任何具体的执行模型—越不像任何单一平台越是好抽象。因为它要给所有平台留出做自己特性的空间。你真正想要的是委托和适配不是统一。6.4 坑四别忽略设备生命周期管理设备生命周期管理是抽象层里很少有人认真设计的部分但它却是最容易出bug的地方。设备热插拔、驱动重启、OOM恢复、上下文重建……这些场景里如果抽象层没有设计好轻则内存泄漏重则直接崩溃。我的建议是把设备生命周期接口单独抽出来和kernel执行、显存管理分开。这样遇到问题时排查范围可以缩小很多。6.5 坑五认证测试必须跟上最后一个坑也是很多项目都会踩的——抽象层开发完成之后没有马上写认证测试。平台接入者做完了冒烟测试但没做压力测试结果上线两天就崩了。所以在我自己的项目里抽象层一旦稳定我第一件事就是写一套跨平台的认证测试集每个平台跑同一套测试。测试覆盖显存分配、kernel执行、换入换出、多设备同步等核心路径。只有全绿的平台才算真正接入完成。7. 最后说几句经验体会写这一整篇不是想介绍什么高深理论而是想说一个很朴素的道理好的抽象层是系统工程里最看不到但最关键的部分。vLLM这次拆掉旧抽象、再造可移植层看起来是在折腾架构实际上是在给自己解锁长期的增长空间。我自己的感受是这类抽象层的设计最考验的不是写代码的能力而是克制的能力——知道哪些细节该进入抽象层、哪些细节该留在平台侧知道接口该有多小、权限边界该画在哪儿。这些判断只能靠一次一次的踩坑换经验。如果你也在做类似的多平台适配或者正在改造自己的模块化架构我强烈建议你把最小接口 平台自由优化 明确边界 持续测试这四件事记在脑子里。尤其是平台自由优化这一条很多人会觉得抽象层就是来统一一切的其实恰恰相反抽象层的价值是要给底层平台留出不被统一的空间。这也是可移植层最微妙的地方它不是把世界变成一个样子而是让世界在多样性中还能协同工作。希望这篇分享能帮到正在折腾架构的你。有问题的话欢迎随时一起讨论。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

正统偶像何解?杨冰怡十一年养成路给出的长期主义答案 2026/10/1 13:23:38

正统偶像何解?杨冰怡十一年养成路给出的长期主义答案

“正统偶像”这四个字,在当下的娱乐语境里几乎快变成一个带着尴尬感的标签。说你传统,像在暗指你过气;说你正统,又像在评价你无聊。我做偶像产业内容观察这行也快十年了,这两年同行之间每次聊到这个词,最后…

阅读更多 →
行李箱缺陷检测数据集:650张2类YOLO+VOC格式实战与避坑指南 2026/10/1 13:23:31

行李箱缺陷检测数据集:650张2类YOLO+VOC格式实战与避坑指南

简介:这份行李箱缺陷检测数据集面向计算机视觉初学者与目标检测开发者,用于训练和验证行李箱外观缺陷识别模型,可支撑工业质检、行李分拣等场景下的二分类检测任务。压缩包共1952个文件,约25.11MB,包含650张jpg图片、6…

阅读更多 →
行李箱缺陷检测数据集:650张2类YOLO+VOC双格式实战指南 2026/10/1 13:23:24

行李箱缺陷检测数据集:650张2类YOLO+VOC双格式实战指南

简介:本资源为行李箱缺陷检测数据集,面向从事目标检测算法训练与验证的开发者、学生及研究人员,可用于行李箱外观质量检测场景下的模型训练与效果评估。压缩包共1952个文件,约25.11MB,包含650张jpg图片、650个xml标注文…

阅读更多 →
普通人如何走好工程师之路:从自学到站稳脚跟的完整指南 2026/10/1 13:23:17

普通人如何走好工程师之路:从自学到站稳脚跟的完整指南

拿到这个标题,我就知道帖主想聊的不只是技术,而是一条完整的成长轨迹。入行多年,我见过太多人把“工程师”理解成单纯的写代码、调接口,结果被现实撞得头破血流。“我的工程师之路,给需要的同学”这个标题,…

阅读更多 →
基于LSTM的电商评论情感分析:从数据清洗到模型部署的完整实战 2026/10/1 13:23:11

基于LSTM的电商评论情感分析:从数据清洗到模型部署的完整实战

简介:这份资源是面向计算机相关专业学生与Python实战学习者的深度学习项目包,以LSTM为核心完成电商购物评论的情感分析任务,可直接用于毕业设计、课程设计或期末大作业。项目围绕京东商城购物评论展开,涵盖数据采集、中文分词与停…

阅读更多 →
KMV与CCA循环违约建模:从原理到Python实战 2026/10/1 13:23:11

KMV与CCA循环违约建模:从原理到Python实战

简介:这份资源面向金融风险管理学习者与量化编程入门者,围绕CCA信用风险评估与KMV违约概率模型展开,重点演示如何通过循环结构逐时间节点计算企业违约距离,进而估计预期违约频率EDF。压缩包共7个文件,以m脚本、docx文档…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉