在连续批处理中解锁异步性
本文解释了如何通过分离CPU和GPU工作负载来大幅提升推理性能。连续批处理通过紧密打包批次提高了GPU利用率,但同步操作导致CPU和GPU交替等待,造成近四分之一的运行时间浪费。通过使用非默认CUDA流和事件实现异步批处理,可以让CPU和GPU并行工作,消除空闲间隙,实现免费的24%加速。文章详细介绍了CUDA流、事件机制以及如何将它们应用于连续批处理,并提供了在transformers库中的实现代码。
文章情报
要点
- 同步连续批处理中CPU和GPU交替工作,导致GPU空闲时间占比约24%。
- 使用非默认CUDA流和事件可以实现CPU和GPU的并行执行。
- 通过H2D、计算和D2H三个流以及事件同步,可以构建异步批处理流程。
- 异步批处理无需新内核或模型更改,即可获得显著的性能提升。
为什么重要
这条新闻值得关注,因为同步连续批处理中CPU和GPU交替工作,导致GPU空闲时间占比约24%。
技术影响
可能影响模型选型、推理成本、产品能力和评测基准。
在AI推理中,GPU的利用率至关重要。H200实例每小时成本约5美元,一天下来就是140美元,因此必须让GPU始终处于工作状态。连续批处理通过紧密打包批次消除了填充浪费,但同步模式下的CPU和GPU交替等待造成了新的浪费。为了确保GPU 100%时间都在计算,我们需要消除这些空闲间隙。本文介绍如何通过异步批处理解决这一问题。
同步批处理的循环中,CPU准备批次时GPU空闲,GPU计算时CPU空闲。在实际分析中,使用批大小32和8B模型生成8K令牌时,总耗时300.6秒,其中24.0%的时间GPU在空闲等待CPU完成。这意味着如果完全消除CPU开销,生成时间可降至228秒,即24%的免费加速。这不需要任何新的内核或模型更改,仅需协调硬件。
实现异步批处理的关键在于使用CUDA流。默认流是同步的,会阻塞其他流,因此必须使用非默认流。文章将GPU操作分为三类:主机到设备(H2D)传输、计算、设备到主机(D2H)传输,并为每种操作分配独立流。但流之间独立运行会导致数据依赖问题,必须使用CUDA事件进行同步。事件是一个标记,可以记录在流中,其他流可以等待该事件完成。例如,计算流必须等待H2D传输完成才能开始计算。
具体实现中,CPU依次提交H2D传输、记录事件、计算流等待事件、计算、记录事件、D2H流等待事件、D2H传输。所有操作在CPU上非阻塞提交,实际执行由GPU调度。这样CPU可以在GPU执行当前批次时立即开始准备下一批次,实现流水线并行。文章还讨论了如何正确使用事件避免死锁,以及如何在transformers库中集成这一优化。异步批处理已在transformers库的连续批处理中实现,代码开源可供参考。最终效果是GPU利用率接近100%,吞吐量显著提升。此外,文章还介绍了CPU启动开销的概念,以及如何通过流和事件实现精确的同步。这些技术细节对于理解异步批处理的工作原理至关重要。