来自:大猿搬砖简记
大家好,大家在读vllm源码解读系列时,肯定会有以下疑惑:“vllm仓库当前主分支的代码,好像和当前文章中展示的代码,存在许多不同之处,这是为什么呢?”
这是因为vllm的开源社区非常活跃,代码一直在持续更新中。更新内容包括:
- 1. 功能优化类更新。
- 2. 代码形式类更新(例如把代码写得更漂亮,更对象化等)
以我读源码时的经验为例,我在整理完调度器部分的两天后,vllm就对调度器做了一次代码重构,那次重构是以2为主,把代码写得更易读了。当然再这之后调度器也经历了很多次功能上的变更,这里就不另说了。
基于此,你肯定想问:“如果vllm代码库更新如此频繁,那么源码解读类文章是不是太old dinosaur了?这类文章能帮到我什么?“
在写源码解读系列的过程中,我曾经犹豫过,要不要换成最新代码版本,或者定期更新文章,提醒读者最近vllm的主要变动。对于后者,工作量实在太大。而对于前者,当我比较了两个月内不同的代码版本后,我的结论是:还不如固定一个代码版本,把它理明白了,然后再去回归线上的版本,这是最事半功倍的操作。
而我得出这个结论的原因是:在多个版本的比较中,我发现vllm代码架构(代码设计的核心思想、核心优化点)其实是比较稳定的。所以想细究源码细节的朋友,其实不必为源码更新速度过快而焦虑(本来大家的阅读速度也是赶不上代码库迭代的速度的),不如通过一个固定版本,先把最核心的东西提练出来,熟悉一下vllm,然后再去对比着看更新的部分,这样也能更好理解vllm为什么做了这些更新操作。
我举一个例子,2周前vllm代码中移除了逻辑块这个东西,目前只有物理块了。当大家初次看到这个更新操作时,肯定觉得这是个大变更,毕竟和paper都完全不一样了!但是如果大家读过之前的代码,就会发现,其实vllm中逻辑块和物理块都是一种“分配方案”,物理块中也不是真正存放着KV Cache,而是后面的CacheEngine根据这种“分配方案”,去实际落地KV cache的计算、读取操作等。如果说物理块是最终的分配方案的话,那么逻辑块其实是计算这种分配方案的中间结果。最新的迭代只是把原来的两步计算合并为一步计算。我们曾经在源码解读系列说过,逻辑块和物理块的映射是靠Sequence类来做的,而其实在最新版中,逻辑块只是形式上消失了,实际上它依然隐藏在Sequence类的各个属性中(例如,sequence类下可以根据token数量计算需要的逻辑块数量n_blocks,也能直接根据token位置确定它在哪块逻辑块中,诸如此类)。很多朋友如果不了解旧代码的操作,看到这样的变更可能会觉得比较奇怪,毕竟大家看完paper的第一反应都是想去看看逻辑块-物理块这种架构的操作逻辑。
最后,对于如何使用源码解读系列来帮助大家阅读vllm代码,我个人的建议是:
- 可以先阅读这篇讲解源码整体架构的文章(文章中所有的架构图皆来自vllm团队meeting ppt,链接附在文章参考部分中了)。
- 然后再下载最新的vllm代码,自行先阅读,看是否有阅读难度,如果没有,完全可以固定住你当前下载的这个版本,把它先理解透,不需为代码频繁变更而着急。
- 如果觉得理解有难度,可以先读源码解读系列,然后对照新版本,着重关注diff部分,理解做这些更新操作的意义。
- 最后,源码解读永远替代不了自己读一遍代码。
希望这篇说明能给正在为vllm代码频繁变更而头疼的朋友代码帮助~
备注:昵称-学校/公司-方向/会议(eg.ACL),进入技术/投稿群
id:DLNLPer,记得备注呦