趋近智
高效内存管理是任何机器学习 (machine learning)运行时系统性能的根本。机器学习模型经常处理大型张量,这需要大量的内存分配。此外,某些模型的动态特性以及推理 (inference)过程中产生的中间激活会导致频繁的分配和释放请求。在性能敏感的循环中,天真地依赖 malloc 或 cudaMalloc 等通用分配器会带来很大的开销和潜在的内存碎片,严重影响执行速度。因此,专门的内存管理策略是必不可少的。
机器学习工作负载带来了独特的内存管理挑战:
在机器学习 (machine learning)运行时中,减轻分配开销最常用的技术是使用竞技场分配器,也称为内存池。其基本思想很简单:
cudaMalloc 用于 GPU 内存,或 mmap/VirtualAlloc 用于 CPU 内存)。竞技场分配器通过从预分配的内存块中进行子分配并管理空闲空间来处理请求的视图。
优点:
实现策略:
策略的选择取决于预期的分配模式、内存限制和性能目标。对于动态形状,竞技场可能需要调整大小,或者可能采用具有不同增长策略的多个竞技场。
如第三章(图级优化)所述,静态内存规划会提前分析计算图,以确定张量生命周期并找到缓冲区共享和重用的机会。这能最大限度地减少内存峰值占用。然而,静态规划依赖于预先知道张量形状。
当存在动态形状时,运行时内存管理器必须处理在执行期间确定大小的分配。即使对图中已知部分进行了静态规划,动态部分也仍非常依赖高效的运行时分配。通常,会采用混合方法:静态规划尽可能地优化,而动态竞技场分配器则处理其余部分,包括根据启发式方法或运行时反馈进行的潜在超额分配,以适应动态大小。
除了竞技场分配器返回已释放块提供的重用之外,运行时还可以实现更积极的显式内存重用。这需要跟踪每个张量缓冲区的活跃度:精确知道缓冲区中的数据何时不再被任何后续操作需要。
一旦缓冲区被识别为“非活跃”,运行时可以立即将其别名为新的分配请求,甚至在生成它的相应操作完全完成之前(前提是同步确保正确性)。这需要与运行时执行调度器(稍后讨论)仔细集成,以正确管理依赖关系。活跃度信息通常由编译器计算,并传递给运行时以指导这些决策。
在 CPU(主机)和 GPU(设备)内存之间传输数据是一个常见的瓶颈。通过 malloc 分配的标准主机内存通常是可分页的,这意味着操作系统可以移动其物理位置。对于 GPU 用于实现高带宽传输的直接内存访问 (DMA) 引擎,物理地址必须是固定的。
因此,从可分页内存发起传输通常涉及一个中间步骤:GPU 驱动程序将数据从可分页源缓冲区复制到主机 RAM 中一个临时的锁定(或页锁定)缓冲区,该缓冲区的物理地址是固定的。然后 DMA 引擎将数据从这个锁定缓冲区传输到 GPU。这个额外的复制增加了延迟并消耗了带宽。
比较使用可分页主机内存与锁定主机内存的数据传输路径。锁定内存允许直接 DMA,消除了暂存复制。
机器学习 (machine learning)运行时通过将参与 GPU 传输的主机端缓冲区直接分配为锁定内存(例如,使用 cudaMallocHost 或 cudaHostAlloc)来优化此过程。
权衡:
运行时必须仔细管理锁定内存分配,通常为锁定缓冲区使用专用竞技场,并且仅在传输性能重要时才审慎分配。
统一内存 (UM) 旨在通过提供一个 CPU 和 GPU 都可以访问的单一、一致的虚拟地址空间,来简化异构系统的编程。程序员只需分配一次内存(例如,使用 cudaMallocManaged),指针即可从任一处理器解引用。
底层系统(GPU 驱动程序、操作系统和硬件)会自动管理物理 CPU DRAM 和 GPU HBM 之间的数据迁移,通常是根据页面错误按需进行。
优点:
cudaMemcpy) 的需要。缺点:
cudaMemAdvise)来指导驱动程序的迁移决策或预取数据(cudaMemPrefetchAsync)。尽管 UM 简化了开发,但高性能机器学习 (machine learning)运行时通常仍偏爱显式内存管理(为 cudaMalloc 和 cudaMallocHost 使用竞技场),并结合与计算内核一同调度的异步内存复制(cudaMemcpyAsync)。这提供了对数据放置和移动的最大控制,通常是实现峰值性能所必需的,尽管在优先考虑开发简单性或特定访问模式下自动迁移表现良好的场景中,UM 也可以是一个可行的选择。
为机器学习 (machine learning)运行时构建高性能内存管理器需要进一步的考量:
总之,高效内存管理是高性能机器学习运行时系统的基础。竞技场分配、内存锁定、基于活跃度的仔细重用以及可能使用的统一内存等技术都是重要的工具。最优策略通常是这些技术的组合,根据具体的机器学习模型、硬件平台和性能要求进行仔细调整。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造