GPU数据传输大提速!英伟达NCCL关键参数大揭秘!
在人工智能浪潮下,图形处理器(GPU)的重要性日益凸显。新媒网跨境了解到,作为一名自媒体原创作者,笔者也在不断学习GPU相关概念,近期对NVIDIA Collective Communications Library (NCCL) 中的一些概念产生了一些疑问,通过查阅资料,整理成此文,希望能与大家共同探讨。由于水平有限,如有不足之处,欢迎指正。
一、NCCL 简介
在高性能计算(HPC)和机器学习领域,多 GPU 系统已成为推动复杂计算任务和大规模数据处理的关键。为了充分利用这些系统中的计算资源,高效的数据通信至关重要。英伟达(NVIDIA)推出的 NCCL (NVIDIA Collective Communications Library) 正是为此而生,它是一个专为 GPU 加速计算设计的高级通信库,旨在简化多 GPU 和多节点系统中的数据同步和传输过程。
NCCL 由英伟达开发,是一个高性能通信库,专为多 GPU 系统设计,旨在加速深度学习、高性能计算等领域的并行计算任务。NCCL 提供了一系列高度优化的集体通信原语,例如 AllReduce、Broadcast、Reduce、AllGather、ReduceScatter 等,以及点对点通信功能,使开发者能够在多个 GPU 之间实现高效的数据传输和同步。
这些通信原语简化了多 GPU 编程,使开发者无需深入了解底层通信细节就能利用多 GPU 的计算潜能。NCCL 支持节点内和跨节点的 GPU 通信,并且在最新的 GPU 架构上进行了优化,比如通过 NVLink 和 PCIe 等技术实现直接的 GPU 到 GPU 通信。
几个常见的通信原语包括:
AllReduce: 将所有 GPU 上的目标数据进行 reduce 操作(例如 sum,max),并将结果写到所有的 GPU 上。
Reduce: 对所有 GPU 的数据进行 reduce 操作(例如 sum,max),并将结果写到用户指定的 GPU 上。
Broadcast: 将 root GPU 上的数据发送到所有 GPU 上,其中 root 可以由用户进行指定。
AllGather: 集合所有 GPU 上的数据,并将集合后的数据写到所有的 GPU 上。
ReduceScatter: 对所有 GPU 上的数据进行 reduce 操作(如 sum max),然后将结果切分到所有的 GPU 上。
从 2.7 版本起,NCCL 实现了点对点通信,点对点通信也是异步方式,调用之后立即返回,用户需要调用 cudaStreamSynchronize 等待聚合通信完成。点对点通信包括 send 和 recive 2 个接口,send 和 recive 需要配对使用,否则可能会导致阻塞。点对点通信给了用户更大的自由度,用户可以通过 send/recive 的组合可以实现诸如 Scatter、Gather、All-to-All 等多种多样的聚合通信操作。
英伟达提供了一个关于 NCCL 的详细指导文档,内容非常丰富,有兴趣的读者可以查阅。
二、GPUDirect 技术演进与解析
GPUDirect Shared Memory (2010 年 6 月引入)
GPUDirect Shared Memory 技术的引入,是 GPU 与第三方 PCI Express 设备间通信方式的一大革新。
这项技术允许 GPU 和外部设备通过共享已锁定的主机内存直接进行数据交换,绕过了 CPU 和系统内存的瓶颈,显著提升了数据传输速度和效率。这在处理大量数据的高性能计算和大数据应用中尤为重要,例如科学模拟、数据分析等领域。
GPUDirect P2P (2011 年)
2011 年,英伟达扩展了 GPUDirect 技术,引入了对同一 PCI Express 根复合体下 GPU 间点对点 (P2P) 直接访问和直接传输的支持。这意味着相邻 GPU 可以在无须经过 CPU 的情况下直接读写对方的显存,极大地减少了数据移动的延迟,尤其对于深度学习等需要频繁在多个 GPU 间同步数据的应用来说,是一个巨大的性能提升。TensorFlow、MXNet 等框架以及 NCCL 通信库均集成了对 GPUDirect P2P 的支持,促进了单机多卡配置下近乎线性的计算性能扩展。
GPUDirect RDMA (2013 年)
2013 年,GPUDirect 技术进一步升级,加入了对远程直接内存访问 (RDMA) 的支持。这项改进使得第三方 PCIe 设备能够绕过 CPU 和主机内存,直接与 GPU 内存交互,进一步降低了数据传输延迟,提升了数据密集型应用的处理速度。这对于构建大规模分布式计算系统,尤其是需要快速访问 GPU 计算结果的存储系统和网络设备来说,是一项关键的技术突破。
三、一些 NCCL 关键参数
NCCL 通信库中有很多环境变量可以调整。新媒网跨境认为,其中有关 P2P (Peer-to-Peer) 与 SHM (Shared Memory 共享内存) 的一些参数值得关注,在此试着解读关于这部分的理解。
1. NCCL_P2P_DISABLE
这是一个环境变量,用于控制 NCCL 是否启用 GPU 间的点对点 (Peer-to-Peer, P2P) 直接通信功能。点对点 P2P 通信允许 GPU 直接交换数据,而无需经过 CPU 或系统内存,这样可以减少数据传输的延迟并提高吞吐量。
在多 GPU 系统中,点对点通信指的是两个 GPU 之间直接的数据交换能力。这通常依赖于硬件级别的直接内存访问 (DMA) 技术,比如 NVLink、PCI Express (PCIe) 或其他高速互连技术,使得 GPU 能够绕过 CPU 直接读写另一个 GPU 的内存。这种直接通信方式大大提高了数据传输效率,尤其是在需要频繁同步数据的并行计算任务中,比如深度学习模型的参数同步。
当设置 NCCL_P2P_DISABLE=1
时,NCCL 将不会尝试使用 GPU 之间的点对点通信通道。这通常是因为系统配置、驱动限制或硬件不兼容导致 P2P 不可用或不稳定。
在 P2P 被禁用的情况下,NCCL 会回退到其他通信机制,比如通过共享内存 (SHM) 进行数据交换。这通常涉及到数据先从一个 GPU 复制到 CPU 内存,然后再从 CPU 内存复制到另一个 GPU,增加了额外的步骤和潜在的性能损失。
2. NCCL_P2P_LEVEL
NCCL_P2P_LEVEL
是 NVIDIA Collective Communications Library (NCCL) 中的一个环境变量,用于控制和优化多 GPU 系统中点对点 (Peer-to-Peer, P2P) 通信的级别和策略。NCCL 是专为加速多 GPU 并行计算和深度学习训练中数据同步的库,它支持高效的集体通信原语,如 AllReduce、Broadcast 等。点对点通信允许 GPU 之间直接交换数据,减少对 CPU 和系统内存的依赖,从而提高通信效率。
自 NCCL 2.3.4 版本起,NCCL_P2P_LEVEL
环境变量允许用户精细化控制 GPU 间何时使用点对点 (P2P) 传输。这一变量定义了 GPU 间最大距离阈值,在此阈值内 NCCL 将采用 P2P 传输方式。用户需指定一个简短的字符串来表示路径类型,以此来设定启用 P2P 传输的拓扑界限。
如果不特别指定,NCCL 将尝试根据运行的架构和环境自动选择最优的 P2P 使用策略。
LOC:指示 NCCL 完全不考虑 P2P 通信,即便 GPU 间存在直接连接也不会启用。
NVL:仅在 GPU 间有 NVLink 直接连接时启用 P2P 通信。
PIX:当 GPU 位于同一个 PCI 交换机上时,允许使用 P2P 传输。
PXB:即便需要跨多个 PCI 交换机跳转,只要 GPU 间可通过 PCIe 链路相连,即启用 P2P。
PHB:在相同 NUMA 节点上的 GPU 间使用 P2P。此时 P2P 通信虽允许,但数据流经 CPU,可能不如直接 P2P 高效。
SYS:跨 NUMA 节点使用 P2P,可能涉及 SMP 互连(如 QPI/UPI)。在不同 NUMA 节点的 GPU 间启用 P2P,可能包含跨越系统间高速互联的情况。
此外,用户还可以使用整数值来设定 NCCL_P2P_LEVEL
,这些数值对应于上述路径类型,保留此选项是为了兼容之前仅支持整数配置的环境。
LOC:0
PIX:1
PXB:2
PHB:3
SYS:4
大于 4 的值将被视为 SYS
。需要注意的是,使用整数值的方式不支持直接指定 NVL
(NVLink)。由于路径类型可能随时间变化,导致整数值对应的含义发生变化,因此推荐使用字符串标识符来避免配置时的困扰和潜在的调试困难。
3. NCCL_P2P_DIRECT_DISABLE
NCCL_P2P_DIRECT_DISABLE
环境变量用于禁止 NCCL 直接通过点对点 (P2P) 在同一个进程管理下的不同 GPU 间访问用户缓冲区。这项设置在用户缓冲区通过不自动使它们对同一进程中其他 GPU 可访问(特别是缺乏 P2P 访问权限)的 API 分配时非常有用。
当设置 NCCL_P2P_DIRECT_DISABLE=1
时,NCCL 在进行通信操作时,即使源和目标 GPU 属于同一个进程中,也会避免直接通过 P2P 方式访问和传输用户分配的内存缓冲区。这一设置主要是为了解决一些特定的内存分配和访问权限问题,确保程序的兼容性和稳定性。
在某些情况下,程序可能会使用特定的内存分配函数或库来创建 GPU 缓冲区,这些分配的内存可能没有默认配置为在所有 GPU 间可直接 P2P 访问。例如,某些第三方库或自定义内存管理方案可能不遵循 CUDA 的标准实践,导致 NCCL 无法直接通过 P2P 访问这些缓冲区。在这种情况下,如果不禁止直接 P2P 访问,可能会导致运行时错误或性能问题。
通过启用 NCCL_P2P_DIRECT_DISABLE
,NCCL 会采取替代路径来完成数据传输,这可能意味着数据会先从一个 GPU 复制到 CPU 内存(或通过其他中介存储),然后再从 CPU 内存复制到目标 GPU。这样的路径显然不如直接 P2P 高效,但在某些特定配置下是必要的,以确保数据的正确传输和程序的正常执行。
在遇到与内存访问相关的错误或性能瓶颈时,可以尝试设置 NCCL_P2P_DIRECT_DISABLE
来解决问题,特别是在使用了非标准内存分配方法时。通常情况下,除非明确遇到兼容性问题,否则保持默认设置(不禁用 P2P 直接访问)是最佳选择,以充分利用 GPU 间的高速通信能力。
NCCL_P2P_DIRECT_DISABLE
提供了一个针对特定情况的解决方案,帮助开发者绕过因内存访问权限或分配方式导致的通信障碍,确保在多样化的系统配置中 NCCL 能够稳定且正确地执行数据传输任务。
NCCL_SHM_DISABLE
NCCL_SHM_DISABLE
环境变量用于禁用 NCCL 中的共享内存 (SHM) 传输方式。共享内存通常在 GPU 间无法直接进行点对点 (P2P) 通信时使用,作为替代路径,通过主机内存来传输数据。当设置 NCCL_SHM_DISABLE=1
后,NCCL 在那些原本会使用共享内存的场景下,将转而使用网络(例如,InfiniBand 或 IP 套接字)在 CPU 插槽间进行通信。
在某些系统配置中,GPU 可能由于硬件或驱动限制,无法有效地利用 P2P 通信。此时,NCCL 通常会退回到使用共享内存作为数据传输的中间站。然而,如果共享内存本身也存在问题或效率低下(例如,内存带宽限制),禁用 SHM 并改用网络通信可能是更优选择。
在拥有高性能网络环境(如 InfiniBand)的多节点系统中,直接通过网络而非共享内存进行 GPU 间的数据交换,有时可以提供更低的延迟和更高的吞吐量,尤其是在跨节点通信时。同时,在资源紧张的环境中,禁用共享内存可以减轻系统内存的压力,避免因过度使用共享内存而导致的其他应用程序性能下降。
四、关于共享内存的理解
在 NCCL 中提到的 SHM,是指在同一个主机节点上,通过操作系统提供的共享内存机制,使得不同进程(或 GPU)能够访问同一块物理内存。尽管名称中有“共享内存”,但这里的 SHM 并不直接等同于 GPU 之间的 P2P 访问,而更多是指通过系统层面的共享内存区间接实现数据交换。在某些情况下,这可能涉及将 GPU 数据复制到 CPU 可访问的系统内存中,再由其他 GPU 读取,或者使用特殊的内存映射技术(如 mmap)使 GPU 直接访问特定的内存区域。
相比 P2P,使用 SHM 可能会增加一些额外的开销,比如 CPU 的协调操作和内存复制。然而,在 P2P 不可用或受限的系统配置下,SHM 提供了一个有效的替代方案来实现 GPU 间的数据共享。SHM 的优势在于其灵活性和兼容性,它可以在不支持直接 P2P 通信的硬件或配置中工作。
此外,笔者还发现 GPU 也有一个共享内存的概念。GPU 内部的流多处理器(Stream Multiprocessors,简称 SM)是执行并行计算的核心组件,每个 SM 负责管理一组 CUDA 核心(或称流处理器)、特殊的函数单元(如 SFU)、以及几种类型的记忆体,其中包括共享内存(Shared Memory)。
这里的共享内存是 GPU 上一种特定类型的一级缓存,它位于每个 SM 内部,设计用于同一个线程块(Thread Block)内的线程间通信和数据共享。与每个线程私有的寄存器(Registers)和局部内存(Local Memory)相比,共享内存具有更快的访问速度和更低的延迟。它的设计初衷是为了提升那些需要在多个线程间频繁访问同一组数据的并行算法的性能,如矩阵乘法、图像处理和卷积神经网络等。
与其它内存类型的对比:
与全局内存相比:全局内存是所有线程均可访问的,但访问延迟高,带宽相对较低。
与寄存器相比:每个线程的私有寄存器访问最快,但数量有限。
与局部内存相比:局部内存实际上是 GPU 上的全局内存的一部分,访问速度慢于共享内存。
因此,GPU 内部 SM 的共享内存的设计旨在通过提供一种高速、低延迟的内存访问模式,促进线程间的数据共享和协同工作,从而提升 GPU 在并行计算任务中的效率。
最后再来对比下:SM (流多处理器) 的共享内存和 NCCL 中的 NCCL_SHM_DISABLE
所指的共享内存虽然都称为“共享内存”,但它们代表了不同层次和目的的内存使用,主要区别在于应用场景、位置和功能上:
SM 的共享内存:
位置与功能:SM 的共享内存位于 GPU 内部,是每个 SM 单元的一部分,专门用于同一线程块(Thread Block)内的多个线程间的数据共享和通信。它是 GPU 架构中的一级缓存资源之一,设计用来减少对较慢的全局内存的访问,提高并行计算的效率。
访问方式:在 CUDA 或类似 GPU 编程模型中,程序员需要显式地声明和管理共享内存的使用,包括分配大小、初始化和同步访问。共享内存的访问控制精细,可以显著减少内存访问延迟,提高数据重用率。
生命周期:其生命周期与调用它的线程块绑定,当线程块执行结束时,共享内存会被回收。
NCCL 中的 NCCL_SHM_DISABLE
共享内存
位置与功能:这里的共享内存指的是主机 (CPU) 内存中的一个区域,当 NCCL 库在进行多 GPU 间的通信时,如果 P2P 通信不可行或被禁用,NCCL 会利用共享内存作为数据传输的媒介。它是一种系统级别的内存共享机制,用于在不同 GPU(通过它们各自的 CPU)之间传递数据,而不是在 GPU 内部线程间共享。
访问方式:NCCL 中的共享内存使用是自动管理的,由 NCCL 库根据环境变量
NCCL_SHM_DISABLE
的设置来决定是否启用。当未禁用时,NCCL 可能会在适当的时候选择使用共享内存作为通信的辅助手段。应用场景:主要应用于多 GPU 通信场景,特别是在 P2P 通信不可用或性能不佳时,作为一种补充手段来加速数据交换。例如,在分布式深度学习训练中,多个 GPU 之间需要高效地交换梯度信息时,共享内存可以作为一种中间缓存,减少对网络通信的依赖。
区别总结:
层次位置:SM 共享内存位于 GPU 内部,服务于单个 SM 内的线程间通信;而 NCCL 中的共享内存是系统层面的概念,位于主机内存中,服务于不同 GPU 之间的数据交换。
功能目的:SM 共享内存侧重于加速单个 GPU 内线程的数据共享和计算效率;NCCL 共享内存则用于解决多 GPU 间数据传输问题,尤其是在 P2P 通信不可行时。
管理方式:SM 共享内存需要程序员在编写 CUDA kernel 时手动管理;NCCL 共享内存的使用则由 NCCL 库根据配置自动处理。
因此,两者虽然都名为“共享内存”,但它们的作用域、使用场景和管理方式均有明显差异。
参考文献:
新媒网 (公号: 新媒网跨境发布),是一个专业的跨境电商、游戏、支付、贸易和广告社区平台,为百万跨境人传递最新的海外淘金精准资讯情报。

Blink Mini 2 (newest model) — Home Security & Pet Camera with HD video, color night view, motion detection, two-way audio, and built-in spotlight — 1 camera (White)
$ 39.99

Blink Video Doorbell (newest model) – Head-to-toe HD view, two-year battery life, and simple setup. Sync Module Core included – System (Black)
$ 69.99

Ring Rechargeable Quick Release Battery Pack
$ 33.42

Amazon Echo Dot (newest model), Vibrant sounding Alexa speaker, Great for bedrooms, dining rooms and offices, Charcoal
$ 38.62

Blink Mini - Compact indoor plug-in smart security camera, 1080p HD video, night vision, motion detection, two-way audio, easy set up, Works with Alexa – 1 camera (White)
$ 29.99











评论(0)