正文
在这个过程中,存在不少算力浪费点,例如 Block 结构不统一导致 kernel 启动频率高,attention 计算利用率低,调度碎片化;跨模态融合模块可能打断计算流水线;输入数据分布不均导致 batch 无法拉大,浪费显存等问题。针对这些问题,我们进行了优化。
例如,进行算子融合,将多个小操作合并成一个复合操作,减少操作的启动次数;利用高效的 attention 计算,如 Flash attention 等,提升 FLOPs 利用率;采用了混合并行加 Interleaved 1f1b 操作,让每张卡在运行当前阶段(Stage)的计算任务的同时,并行准备下一步的前向(Forward)或反向(Backward)计算,从而打通 pipeline,提升整体吞吐效率;还可以进行激活重算、混合精度等操作,释放显存,进一步拉大 batch size,使每张卡都能充分发挥性能。
节点内通信通常问题不大,但跨节点的 AllReduce 操作容易遇到带宽瓶颈,导致 GPU 空等。多跳网络路径在 checkpoint 写入 / 读取时显著增加延迟,拖慢整体训练。我们归纳出四类常见问题:跨节点带宽受限、通信与计算不重叠、多流调度不均、拓扑与并行策略不匹配。
针对这些问题,我们采用了以下优化:
-
拓扑感知调度
:根据物理交换机层级和机架分布,最小化通信路径长度。
-
通信 - 计算重叠
:在 CUDA Stream 上并行调度 AllReduce 与前向/反向计算。
-
NCCL 多通道
:启用多网络接口或多 NVLink 通道并行传输,分散热力学热点。
-
CPU 核绑定
:将通信线程绑定至特定 NUMA 节点的 CPU 核心,减少远程访问延迟并提升稳定性。
只有通信顺畅,整个训练才能顺利进行。
多模态训练周期长、数据量大、集群规模大,出现中断的概率显著提高,且重启代价高昂。我们围绕以下三方面进行系统性优化:
以上优化结合了 NVMe 加速写入、异步缓存读取和分布式任务重试等业界最佳实践,实现了多模态大规模训练的长跑与稳跑目标。
接下来,我将通过一些具体的案例,深入探讨图文理解模型 LLaVA 和文本生成图像模型 DiT 的优化实践。这两种模型类型不同,痛点各异,优化路径也各有侧重。通过具体案例的拆解,大家能够更直观地看到它们在工程实践上面临的挑战。
我们对 LLaVA 和 DiT 的模型结构进行了整体对比。LLaVA 的模型结构是从 ViT 抽取图像特征,经过投影对齐到文本空间,最后通过大语言模型进行问答输出。而 DiT 的生成模型则是图像由 VAE encoder 得到 latent,文本由 CLIP/text Transformer encoder 得到 embedding,再逐步还原出最终的图像。
尽管一个是理解模型,另一个是生成模型,但在训练落地时,它们都面临着四大共性挑战:多模态数据对齐难,I/O 压力大;模型结构复杂,融合难度高;通信开销大,容易产生阻塞;训练容易中断,容错要求高。因此,我们从数据处理、模型计算、通信效率提升以及稳定性优化等方面入手,为它们提供保障。
在大规模模型训练中,数据加载往往是第一个瓶颈。如果加载速度慢,GPU 可能会空闲,导致算力浪费;而加载进程过多,又容易占用过多内存,引发系统内存溢出等问题。
我们通过监控 GPU 端数据接收的耗时来发现问题,一般来说,耗时在毫秒级是正常的,如果耗时上升,就可能意味着读取数据出现了问题。数据供应不足会导致整个训练链路变慢。
为此,我们从四个方面对链路系统进行了优化:一是优化任务下发,使其更轻量,主进程统一生成列表,并发地给多个子进程加载,减少调度负担;二是在子进程中进行解码或 resize 操作,避免主进程阻塞;三是启用锁页内存(Pin Memory),让数据流转更高效;四是在拉取数据时,利用本地缓存,避免频繁跨节点读取高频数据,直接从本地缓存拉取。