返回

文章详情

破灭GPU泡沫

Hacker News2026年6月30日 05:14

Moondream工程公司的Photon,Moondream的推理引擎,达到了近实时的VLM推理(在NVIDIA B200上的时间约为33毫秒)。这是一个关于它如何通过优化GPU的工作方式实现高达35%的解码吞吐量提升的简介。2026年6月4日,您如何使AI模型尽可能快地运行?这是我们在Moondream总部所关心的问题。GPU处理所有涉及模型推理的数学,因此乍一看似乎没有太多复杂之处:只需告诉它该做什么并等待答案。但如果您开始查看其实际工作原理,您会发现GPU经常闲置,不是因为缺乏工作,而是因为CPU尚未告诉它接下来该做什么。这种现象被称为GPU泡沫。当典型的AI模型生成文本时,它一次只生成一个token(token是一段文本,约为几个字符)。每个token都依赖于之前的token,这是一个称为自回归的属性,因此生成是顺序的。在获得第二个token之前,您无法计算第三个token。这个解码循环涉及CPU和GPU之间的往返。GPU承担了大部分实际模型运行的繁重工作,进行数十亿的算术运算以生成下一个token。但CPU也做了大量意想不到的工作。它选择接下来要运行的请求,设置GPU所需的元数据,从模型输出中挑选出实际的token并记录它,还有更多工作。挑战在于,一个token所需的GPU工作量很小,而CPU的维护工作是每次往返都要付出的固定成本。如果GPU必须等待这些维护工作才能开始下一个token,它就会在每个循环的部分时间内处于空闲状态。这就是我们为什么会出现GPU泡沫。在这篇文章中,我们将深入探讨Photon如何使用一种称为流水线解码的技术来隐藏这些泡沫。其理念是重叠这两种工作:我们在CPU仍在完成最后一个token时开始下一个token的GPU工作。问题的形状如下。在阻塞版本(顶部),每个步骤都是一个接力。CPU计划并启动一个前向,GPU运行它,然后CPU同步,等待结果到达,提交它们,然后才开始计划下一个步骤。这是因为计划依赖于我们选择的token。例如,如果模型指示它已经完成回答,那么我们需要从队列中安排一个新的待处理请求。GPU闲置,等待CPU完成其提交-计划-启动的工作。修复方法是对循环进行流水线处理。在当前步骤的token仍在返回并被提交时启动下一步的前向。这就是流水线版本(底部):前向运行接连不断,CPU工作在它们之下重叠。我们之所以能够这样做,是因为我们刚刚采样的token不必离开GPU。下一个前向直接从GPU内存读取它作为输入。我们最终仍然希望在CPU上有一个副本,以进行去token化、流式传输并决定请求是否完成,但这是我们稍后可以在后台完成的簿记工作,而下一个前向已经在运行。不等待该副本就是消除泡沫的举动。确保其安全需要三件事,我们将在本文剩余部分中讨论:保持步骤缓冲区不冲突(乒乓槽)、获得约束解码的采样顺序(现在前向,稍后采样),以及在请求完成后进行清理(僵尸)。机制1:乒乓槽 为了运行解码步骤,GPU需要一组工作缓冲区:一个用于暂存输入的地方(最后生成的token及其在序列中的位置)、一个用于模型写输出的地方(logits,每个词汇的得分)、一个用于存放采样token的地方,以及一些注意力内核需要查找每个序列的缓存键和值(KV缓存)的簿记工作。我们在两端保持固定(页面锁定)的主机缓冲区,因此在GPU内外的复制作为后台DMA(直接内存访问)传输运行,而不是阻塞CPU。这些缓冲区只分配一次,并在每一步中重复使用。我们努力避免在运行时进行GPU内存分配,因为这可能导致设备同步并引入泡沫。还需要固定的缓冲区地址来一次捕获解码步骤作为CUDA图形并重放它,从而减少内核启动的开销。我们将这个集合称为DecodeSlot。这是可行的,但引入了对管道化的阻塞。缓冲区在步骤完成之前保持使用状态,因此我们不能在当前步骤完成之前开始下一步。为了重叠两个步骤,第二步需要其自己的工作集,否则它可能会在CPU读取这些结果之前覆盖第一个步骤的结果。因此,我们保持两个槽,并轮流使用它们,以乒乓的方式进行。一件需要注意的事情是启动:我们不会在从CPU发出启动的瞬间就执行内核。相反,我们将它们排队到一个流中——一个GPU按顺序处理的有序队列。在此描述中...

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡