最近给朋友介绍了一下我对于一些外部资料的吸收的经验。我想了想整理了下聊天记录,将我整个思路以博客的形式展现出来。希望能帮到看这篇博客的人。

正文

首先说明,我自己看过关于知识体系方法论的资料很少。本文描述的是我自己在这些年经过不断改良后觉得目前最适合我的一套方法,可能不适合所有人,仅供参考

我自己的宗旨是 “有些时候我不一定需要成为知识的生产者,而是成为知识的搬运者”

或者套用鸭子类型的一个描述就是“如果一个项目,你知道原理,理解细节,能完整的给别人分享其中的细节,那么这就是你做过的项目”

成为一个合格的知识搬运者,那么意味着你需要擅长或者说能较好的吸收一些外部资料。我自己将原则归纳为两点

  1. 摆正心态
  2. 知识迁移

这里我先要着重强调心态上的重要性,再开始去描述我们怎么样去做知识的迁移

我自己对于心态是这样的观点:很多人对于去内化别人的资料有一种潜在的耻辱性心态,大家在面对一些资料的时候,会下意识的有“这不是我做的”,“我好菜啊”,“好难懂”心态,而不是抱着“原来我可以这么做”,“原来我之前这么做是对的”,这个心态将决定了你知识吸收的效率。

在我们聊完心态的重要性后,我将以之前看到的一篇 Mooncake 分离式推理架构创新与实践 的文章为例子,大致的描述我怎么样将一篇资料消化的

这篇文章比较清晰的介绍了 Mooncake 在一些场景下的面临的挑战和解决思路。我们现在来逐行拆分一些我消化过程中觉得关键的点

在继续之前,我将这个过程总结为

  1. 知识验证
  2. 平行迁移
  3. 知识增强
  4. 新领域启发

这四部曲,以及如果你在面对一些可能是你看来比较 naive 的资料,可能还会有一部分我称之为对抗性思路的过程,即你需要去思考,如果是你,你会怎么样做的比他好?

首先我们聊一下第一部分知识验证的过程

比如以上文提到的资料中这样一段资料

第一段

除了性能挑战,我们还需要在大规模推理时采用一些自动运维手段,以减少人力投入,专注于解决更重要的问题。为此,我们采取了以下措施:首先,我们实现了推理实例的快速切换和快速拉齐方法。由于显卡是容易损坏的硬件,我们有硬件巡检手段,能够在机器出现问题时快速隔离,并在一定时间内如果无法恢复则人工介入。其次,在深夜时段,推理压力不大时,我们会释放一部分空闲资源来执行一些长时间或离线的任务,这些任务对延迟不敏感,可以异步进行。或者将这些机器用于一些轻量级的训练任务,以避免资源闲置。

第二段

首先,针对 Prefill Cache Miss 的问题,关键在于机器 B 没有热请求的 KV Cache。我们的解决方案是采用 Prefil 到 Prefill 的 Cache Transfer。当机器 B 发现没有 KV Cache时,我们不选择重新计算,因为这会消耗大量时间,而是让机器 A 直接将 KV Cache 传输给机器 B。这样,机器 B 就可以打破恶性循环,减少 TTFT 压力,提高并行度。
其次,我们需要处理 Prefil 到 Decode 的传输,这使得我们的 RDMA 网络带宽使用非常频繁。因此,我们需要一个更优的 RDMA 传输方案。许多开源工具的实现可以达到 80GE的水平,但离理论上限还有一定距离。我们对 RDMA 传输进行了精细调整,使得传输速率可以达到 180GB 每秒,非常接近 200GB 的理论上限。

这两部分资料提到的有两个东西

  1. 自动化巡检
  2. 对于缓存系统的 Prefetch 预热

这一部分实际上是对于我已有知识的验证,我会去思考过去做过的自动化巡检系统中的一些细节(包括怎么样提升准确性,减少误报等关键点),以及验证我自己之前做过的一些缓存预热的手段。

当然实际上在看这一部分的时候还包含了一些知识的增强。比如在这个过程中我会去查询目前 RDMA 开源方案的一些瓶颈,同时去查阅一些调优的文章。这样确保即便我没做过 RDMA 相关的部分,我也能对这样一个知识领域有一些最基本的了解

OK,我们来看第二步,知识的平行迁移

我们总结了几个关键公式:
更低的推理成本 =更省的模型结构 + 更便宜的硬件
更便宜的 Long Context= 更快的 Attention 计算 + 更小的 KVCache
更便宜的 Generation =更大的 Batch Size+更 Decode 友好的并行方式
这里所说的更节省的模型结构,指的是在时间和显存上的优化。如果我们进一步拆分推理成本,会发现两个关键点:一是长上下文的 Prefil(预填充),二是 Generation(生成)的成本。对于长上下文的预填充,我们知道 Attention(注意力机制)具有平方级的时间复杂度。随着上下文长度的增加,比如达到 64K或一兆,所需的时间也会呈平方级增长,这成为我们系统中非常关键的一部分。因此,我们需要对这种场景进行专门的优化。优化长上下文预填充后,我们发现从整体上看,生成的成本才是推理系统的主要成本。因为用户在对话过程中需要模型输出的字数越来越长,而生成是一个 Memory Bound 的过程。

这里是文章开头中介绍 Mooncake 这一套系统的背景。在我看来,这一段可能技术上可以吸收的点并不多。但是这一段包含了很不错的演讲分享技巧。

  1. 用简单清晰的公式去吸引观众的注意
  2. 用 “比如达到 64K或一兆,所需的时间也会呈平方级增长” 这样精炼而吸睛的描述去做一个关键点的突出

这一样一组技巧,我会直接吸收下来作为我自己后续演讲准备中的一些素材。我自己也会在脑海中构建一个场景,如果时间回到21年,我在阿里晋升答辩的时候,如果让我用现在的技巧去概括我过去一年在网关中做的一些关键工作,我会怎么样去概述。

OK,现在我们来看第三步,知识的增强

我们的优化工作带来了显著的收益,这些收益体现在几个关键指标上。首先,我们实现了TTFT 的 10 倍提升,这主要得益于 Cache Miss 的显著降低,目前我们能做到小于 10%的 Cache Miss 水平,大量的计算可以被重复利用。
其次,我们在 TBT 上获得了大约5 倍的提升。这主要归功于 decode 节点能够将 batchsize 增大两倍以上。如果我们采用 Prefi 和 Decode 混合部署的方式,Decode 节点的TVT(Time to Value)压力会比较大,因为需要在 Decode 之间插入 Prefil 的计算。但如果我们将 Prefi 和 Decode 分离, Decode 节点就不需要为 prefil 预留任何显存,从而可以增大 batch size。尽管如此,batch size 的增加也会导致 TBT 相应下降,因此在SLO 的限制下,我们最终只能达到两倍多的水平。
在总体吞吐量上 RPM 上,我们平均获得了 1.7 倍的提升,对于一些较简单的业务,提升甚至超过了 5 倍。这些成绩的取得,是因为我们挖掘了当前许多框架可能没有充分利用的硬件资源,例如基础架构的 RDMA 通信带宽、内存的容量和带宽,以及 OSS 或 SSD 等多级缓存工具。

我是一个做 infra 出身的 SRE,那么对于可观测性的渴望我是吸纳在骨子里的,在看到这一段 Mooncake 关键结果的描述的时候,我会去思考这样一些问题

  1. 他们的监控规模有多大?时序数据规模有多大?采用的什么方案?Prometheus 等开源结构能否满足这一套需求?
  2. 他们这种对于 cache 的访问场景是不是延时敏感的?如果是的话,要去监控 cache miss 等指标的 overhead 会有多大?

我会在我脑海中根据我已经有的信息,对我自己给自己提出的问题进行一次或者多次推演(通常我工作累了,会做一些类似的推演或者思考来换个脑子休息一下)。而其有机会的时候,我也会去请教作者我思考过程中的一些问题(比如之前看一些论文或者内核 Patch 我有些思考都会直接去邮件沟通作者)。而不断的推演以及和同行不断的交流,实际上是对于知识的一个正向的反馈过程。能够帮助你对你自己做过的东西理解的更深。

OK,现在我们来聊新领域的启发

以前面的例子为例,整篇文章中反复提到了他们利用 RDMA 所做的一些事情。而这一块其实是我知识的盲区所在。所以我会去做以下这一样一些探索

  1. 明确 RDMA 目前的发展的一些状况
  2. 找一到两篇关于 RDMA 的论文进行粗读
  3. 找一到两篇公开的分享来了解 RDMA 在业界的一些落地概况

我自己日常的场景离 RDMA 可能有不少的 GAP。但是这样一些新领域的探索不仅能让我对 RDMA 有一些最基本的认知。也能让我去对行业头部的发展有一些理性的认识。

在我看来,知识消化其实就是不断的从你觉得有用的资料中重复这四部曲的过程。你需要基于你已有的知识框架去做一些推演,做一些思考。最终,别人的知识也可以成为你的知识.jpg

“我们不是知识的生产者,我们是知识的搬运工.jpg”

总结

差不多就这样吧,希望这篇文章能帮到大家