How to Streamline Shared Memory Space With the NVSHMEM Communication Library

Akhil Langer, Seth Howell, Jim Dinan, Nvidia | GTC Spring 2023

目录


1. 通信模型

1.1 CPU发起的通信

CPU-Initiated Communication Timeline (Page 2)
CPU-Initiated Communication Timeline (Page 2)

特点:

普遍使用的模型,但存在问题:
* 在关键路径中存在卸载延迟(Offload latencies in critical path)。
* 通信未重叠(Communication is not overlapped)。
* 隐藏这些延迟会增加代码复杂性。
* 不隐藏延迟会限制强扩展性。

1.2 GPU发起的通信

GPU-Initiated Communication Timeline (Page 3)
GPU-Initiated Communication Timeline (Page 3)

特点:
* 在GPU上进行计算。
* 由GPU发起通信。

优点:
* 消除了卸载延迟(Eliminates offload latencies)。
* 计算和通信重叠(Compute and communication overlap)。
* 通过线程隐藏延迟(Latencies hidden by threading)。
* 更易于用内联通信表达算法(Easier to express algorithms with inline communication)。

目标: 在提升性能的同时,简化编程。


2. NVSHMEM 概述

2.1 NVSHMEM 简介

OpenSHMEM,为NVIDIA GPU集群上的最佳性能而适配

NVSHMEM Architecture (Page 5)
NVSHMEM Architecture (Page 5)

2.2 NVSHMEM 对称内存模型

独立分区聚合到全局地址空间

NVSHMEM Symmetric Memory Model (Page 6)
NVSHMEM Symmetric Memory Model (Page 6)

2.3 NVLink 通信优化

使用第四代NVLink无缝扩展至256个GPU

NVLink Scale-Up and InfiniBand/RoCE Scale-Out (Page 7)
NVLink Scale-Up and InfiniBand/RoCE Scale-Out (Page 7)

2.4 纵向和横向扩展带宽

Bandwidth Charts (Page 8)
Bandwidth Charts (Page 8)

理论对等体双向带宽 (GB/s)

理论网络注入 + 弹出带宽每GPU (GB/s)
* 100Gb ConnectX-5 (DGX V100):25
* 200Gb ConnectX-6 (DGX A100):50
* 400Gb ConnectX-7 (DGX H100):100

2.5 线程级通信

Thread-Level Communication Diagram and Code (Page 9)
Thread-Level Communication Diagram and Code (Page 9)
_global_ void stencil_single_step(float *u, float *v, ...) {
    int ix = get_ix(blockIdx, blockDim, threadIdx);
    int iy = get_iy(blockIdx, blockDim, threadIdx);

    compute(u, v, ix, iy);
    // Thread-level data communication API
    if (iy == 1)
        nvshmem_float_p(u+(ny*1)*nx+ix, u[nx+ix], top_pe);
    if (iy == ny)
        nvshmem_float_p(u+ix, u[ny*nx+ix], bottom_pe);
}

for (int iter = 0; iter < N; iter++) {
    swap(u, v);
    stencil_single_step<<<..., stream>>>(u, v, ...);
    nvshmem_barrier_all_on_stream(stream);
}

2.6 线程组通信

Thread-Group Communication Diagram and Code (Page 10)
Thread-Group Communication Diagram and Code (Page 10)
_global_ void stencil_single_step(float *u, float *v, ...) {
    int ix = get_ix(blockIdx, blockDim, threadIdx);
    int iy = get_iy(blockIdx, blockDim, threadIdx);

    compute(u, v, ix, iy);
    // Thread block-level communication API
    int boffset = get_block_offet(blockIdx, blockDim);
    if (blockIdx.y == 0)
        nvshmemx_float_put_nbi_block(u+(ny*1)*nx+boffset, u+nx+boffset, blockDim.x, top_pe);
    if (blockIdx.y == (blockDim.y-1))
        nvshmemx_float_put_nbi_block(u+boffset, u+ny*nx+boffset, blockDim.x, bottom_pe);
}

for (int iter = 0; iter < N; iter++) {
    swap(u, v);
    stencil_single_step<<<..., stream>>>(u, v, ...);
    nvshmem_barrier_all_on_stream(stream);
}

2.7 核内同步

In-Kernel Synchronization Diagram and Code (Page 11)
In-Kernel Synchronization Diagram and Code (Page 11)
_global_ void stencil_multi_step(float *u, float *v, int N, int *sync, ...) {
    int ix = get_ix(blockIdx, blockDim, threadIdx);
    int iy = get_iy(blockIdx, blockDim, threadIdx);

    for (int iter = 0; iter < N; iter++) {
        swap(u, v);
        // Thread block-level data exchange (assume even/odd iter buffering)
        int boffset = get_block_offet(blockIdx, blockDim);
        if (blockIdx.y == 0)
            nvshmemx_float_put_nbi_block(u+(ny*1)*nx+boffset, u+nx+boffset, blockDim.x, top_pe);
        if (!((blockIdx.y == (blockDim.y-1))))
            nvshmemx_float_put_nbi_block(u+boffset, u+ny*nx+boffset, blockDim.x, bottom_pe);

        this_grid.sync();
        if ((!itid) nvshmem_barrier(); // Be aware of synchronization costs. Best synchronization approach is application dependent!
        this_grid.sync();
    }
}

更多详情:https://github.com/NVIDIA/multi-gpu-programming-models

2.8 流序操作

NVSHMEM CPU发起的在CUDA流和图上入队的操作

Stream-ordered Operations Diagram (Page 12)
Stream-ordered Operations Diagram (Page 12)

2.9 集体核函数启动

确保使用设备侧核间同步时的进度

Collective Kernel Launch Table (Page 13)
Collective Kernel Launch Table (Page 13)
NVSHMEM 用法 CUDA 核函数启动
设备发起的通信 执行配置语法 <<<...,>>> 或启动API
设备发起的同步 nvshmemx_collective_launch

2.10 与CUDA图的互操作性

CUDA Work in Streams to Graph of Dependencies (Page 14)
CUDA Work in Streams to Graph of Dependencies (Page 14)

2.11 与MPI/OpenSHMEM的互操作性

通过基于属性的初始化例程启用

MPI and OpenSHMEM Initialization Code Snippets (Page 15)
MPI and OpenSHMEM Initialization Code Snippets (Page 15)

MPI:
使用MPI_COMM_WORLD初始化NVSHMEM。

MPI_Init(&argc, &argv);

MPI_Comm mpi_comm = MPI_COMM_WORLD;
nvshmemx_init_attr_t attr;
attr.mpi_comm = &mpi_comm;
nvshmemx_init_attr(NVSHMEMX_INIT_WITH_MPI_COMM, &attr);

mype_node = nvshmem_team_my_pe(NVSHMEMX_TEAM_NODE);
CUDA_CHECK(cudaSetDevice(mype_node));

OpenSHMEM:
使用SHMEM默认上下文初始化NVSHMEM。

shmem_init();

nvshmemx_init_attr_t attr;
nvshmemx_init_attr(NVSHMEMX_INIT_WITH_SHMEM, &attr);

mype_node = nvshmem_team_my_pe(NVSHMEMX_TEAM_NODE);
CUDA_CHECK(cudaSetDevice(mype_node));

3. NVSHMEM 最新特性

3.1 发布 NVSHMEM 2.9.0

自 NVSHMEM 2.5.0 / GTC Spring 2022 以来新增的特性:

3.2 GPUDirect Async 内核发起通信

与 Mellanox NICs 更紧密的集成

GPUDirect Async Kernel Initiated Communication
GPUDirect Async Kernel Initiated Communication

3.3 GPU-发起 (IBGDA) 与代理通信性能

在 2kB 和 16kB 传输大小下的全带宽

GPU-Initiated (IBGDA) vs Proxy Communication Performance
GPU-Initiated (IBGDA) vs Proxy Communication Performance

3.4 标量 Put 合并

将多个 NVSHMEM "p" 操作合并为一个工作请求
* IBGDA 合并 (IBGDA Coalescing) 在 128 个 CTA 时达到 1935 MOPS 的消息速率,远高于 IBRC 的 180 MOPS 和 IBGDA 的 1.7 MOPS。

Scalar Put Coalescing
Scalar Put Coalescing

3.5 二进制分发改进

改进了可移植性和可用性
* HPC_SDK 在多个平台上分发 NVSHMEM 及其他兼容软件包。
* HPC_SDK 中使用的 NVSHMEM 二进制包的近期更改通常也很有用。
* NVSHMEM 现在支持 CUDA 次要版本兼容性。
* 编译器限制:所有静态链接的部分必须使用最旧的编译器版本构建。

BINARY DISTRIBUTION IMPROVEMENTS
BINARY DISTRIBUTION IMPROVEMENTS

3.6 CMAKE 构建系统

CMAKE BUILD SYSTEM
CMAKE BUILD SYSTEM

3.7 内联设备代码

改进了延迟
* 设备 API 实现:
* P2P 内存复制 (内联)
* 远程通信 (未内联)
* 集合 API 实现 (未内联)

INLINING DEVICE CODE
INLINING DEVICE CODE

3.8 集合优化

3.8.1 使用 LL 协议改进延迟

Collectives Optimizations
Collectives Optimizations

3.8.2 拓扑感知优化

Collective Optimizations
Collective Optimizations

4. 性能案例研究

4.1 NVSHMEM + cuFFT = cuFFTMp

NVSHMEM + cuFFT = cuFFTMp
NVSHMEM + cuFFT = cuFFTMp

4.2 NVSHMEM 在 GROMACS 中的应用

NVSHMEM IN GROMACS
NVSHMEM IN GROMACS

4.3 NVSHMEM 在高性能 Linpack (HPL) 中的应用

NVSHMEM in High Performance Linpack (HPL)
NVSHMEM in High Performance Linpack (HPL)

5. 即将推出的特性和结论

5.1 NVSHMEM 中的 Grace Hopper 支持

本节详细介绍了 Grace Hopper 超级芯片架构及其在 NVSHMEM 中的支持。

5.2 第四代 NVLink

第四代 NVLink 进一步增强了互联性能。

5.3 NVSHMEM 内存空间与上下文

本节阐述了 NVSHMEM 内存空间和上下文,以实现对 Grace CPU 内存的访问并改进通信管理。

5.4 总结

NVSHMEM 是一个用于 NVIDIA GPU 集群的 PGAS (Partitioned Global Address Space) 库。

5.5 NVSHMEM 状态

NVSHMEM 的最新发布信息和关键特性。