0 overall

Hopper (H100 起)引入的新特性——NVLink SHARP 多播内存(Multicast Memory)机制。

  • 通过 cuMulticastCreate创建组播对象,可以让部分内存操作在多个device上被hardware直接broadcast。
  • 通过使用 cuMulticastAddDevice讲device加入到组播对象中。
  • 每个参与组播的device可以用 cuMulticastBindMemcuMulticastBindAddr将自己的内存绑定要这个组播对象上。
  • 组播的对象可以通过VMM的api(cuMemMap && cuMemSetAccess)映射成某个设备的VA。

1 functions

1.1 cuMulticastGetGranularity

CUresult cuMulticastGetGranularity (size_t* granularity, const CUmulticastObjectProp* prop, CUmulticastGranularity_flags option) 计算指定多播对象属性下的最小或推荐粒度。

  • granularity:返回的粒度值。
  • prop:多播对象属性的结构体,这里需要填的就是设备数量,multicast需要的memory大小,可导出的handle的bitmask的类型(一般就是FD或者Fabric)。
  • option:选择返回最小(MINIMUM)或推荐(RECOMMENDED)粒度。

返回的granularity用来设置multicast对象的大小、绑定offset和地址映射的对齐。拿到granularity大小和prop之后,去下一步的create。

1.2 cuMulticastCreate

CUresult cuMulticastCreate ( CUmemGenericAllocationHandle* mcHandle, const CUmulticastObjectProp* prop) 根据刚刚的prop属性创建一个multicast对象,并返回handle。

  • mcHandle:输出参数,返回新创建的多播对象句柄。
  • prop:描述多播对象的属性结构体。
  1. 参与的设备数量由 propnumDevices 指定。创建后必须通过 cuMulticastAddDevice 添加所有设备。
  2. 绑定内存方法是:cuMulticastBindMem 或 cuMulticastBindAddr。解绑内存使用 cuMulticastUnbind。
  3. 每个设备可绑定的总内存量由 propsize 指定。必须是 cuMulticastGetGranularity(…, CU_MULTICAST_GRANULARITY_MINIMUM) 的倍数。或者是对齐到cuMulticastGetGranularity(…, CU_MULTICAST_GRANULARITY_RECOMMENDED) 获得最佳性能。
  4. 添加完所有设备之后就可以使用VMM的API(cuMemMap,cuMemSetAccess)将multicast映射到VA空间去使用。
  5. 如果跨进程共享的话就需要去用 cuMemExportToShareableHandle 生成可共享句柄,同时必须在 prophandleTypes 里指定句柄类型。
  6. 释放多播对象则使用 cuMemRelease。

1.3 cuMulticastAddDevice

CUresult cuMulticastAddDevice ( CUmemGenericAllocationHandle mcHandle, CUdevice dev ) 把某个设备加到已经create完的multicast object内。

  • mcHandle:代表多播对象的句柄。
  • dev:要加入多播组的设备。 设备总数由 CUmulticastObjectProp::numDevices 在 cuMulticastCreate 时指定。需要注意的是:
  1. 调用 cuMulticastBindMemcuMulticastBindAddr 之前,必须确保所有设备都已添加;
  2. 同样,调用 cuMemMap(映射多播内存)之前,也必须完成所有设备的添加;
  3. 若未完成添加,这些函数将会阻塞(等待)

1.4 cuMulticastBindAddr 和 cuMulticastBindMem

CUresult cuMulticastBindAddr ( CUmemGenericAllocationHandle mcHandle, size_t mcOffset, CUdeviceptr memptr, size_t size, unsigned long long flags ) 把一个VA的内存绑定到multicast object上。就是由 memptr 指定的内存区域(必须cudaMallocAsync()或者cuMemCreate分配的内存)绑定到 mcHandle 所表示的多播对象上。

  • mcHandle:多播对象句柄。
  • mcOffset:多播地址空间中的偏移量。
  • memptr:要绑定的内存的虚拟地址。
  • size:要绑定的内存大小。
  • flags:保留参数,目前必须为 0。

注意点是:

  1. size、mcOffset、memptr 都必须是由 cuMulticastGetGranularity(…, CU_MULTICAST_GRANULARITY_MINIMUM) 返回的最小粒度的倍数。最佳性能就是把这三个对齐到RECOMMEND返回推荐粒度。
  2. 绑定的大小不能超过该内存分配本身的大小;
  3. size + mcOffset 不能超过整个多播对象的大小;
  4. 绑定的内存必须来自于已加入该多播组的某个设备。
  5. 如果资源不足,会返回 CUDA_ERROR_OUT_OF_MEMORY;若系统驱动未准备好,则返回 CUDA_ERROR_SYSTEM_NOT_READY;若系统状态非法(驱动守护进程未运行等),会返回 CUDA_ERROR_ILLEGAL_STATE。

CUresult cuMulticastBindMem ( CUmemGenericAllocationHandle mcHandle, size_t mcOffset, CUmemGenericAllocationHandle memHandle, size_t memOffset, size_t size, unsigned long long flags ) 与上面的区别就是这里用的不是VA,而是它的handle和在内存里的偏移。

  • mcHandle:多播对象句柄。
  • mcOffset:在多播对象中的偏移。
  • memHandle:表示要绑定的内存的句柄。
  • memOffset:在内存中的偏移。
  • size:要绑定的内存大小。
  • flags:目前必须为 0。

所有偏移量和大小都必须是 cuMulticastGetGranularity 返回的最小粒度的整数倍。 同样,为获得最佳性能,应对齐到推荐粒度。其他的要求与上面一致。

1.5 cuMulticastUnbind

CUresult cuMulticastUnbind ( CUmemGenericAllocationHandle mcHandle, CUdevice dev, size_t mcOffset, size_t size ) unbind指定device上绑定到multicast object的内存区域。

  • mcHandle:多播对象句柄。
  • dev:包含绑定内存的设备。
  • mcOffset:在多播对象中的偏移量。
  • size:要解绑的大小。

解除绑定的偏移与大小必须是 cuMulticastGetGranularity(…, MINIMUM) 的倍数。 size + mcOffset 不能超过多播对象总大小。mcOffset 和 size 必须与绑定时使用的值完全一致,否则行为未定义。