0 overall

1️⃣ cuMemAddressReserve → 2️⃣ cuMemCreate → 3️⃣ cuMemMap → 4️⃣ cuMemSetAccess → 5️⃣ cuMemUnmap → 6️⃣ cuMemRelease → 7️⃣ cuMemAddressFree (其中 cuMemExportToShareableHandle / cuMemImportFromShareableHandle 为可选,用于跨进程共享;多播内存 cuMulticast* 相关为可选分支)

1 functions

1.1 cuMemGetAllocationGranularity

CUresult cuMemGetAllocationGranularity ( size_t* granularity, const CUmemAllocationProp* prop, CUmemAllocationGranularity_flags option ) 计算最小或者推荐的粒度。

  • granularity 输出粒度。
  • prop 要查询的内存分配属性。
  • option 指定要返回的粒度类型(最小或推荐)。

根据指定的分配属性计算最小或推荐粒度,并将结果返回到 granularity。粒度值用于保证分配、映射、对齐参数的正确性。通常用于确定 size、offset 或 ptr 是否符合对齐要求。

1.2 cuMemAddressReserve

CUresult cuMemAddressReserve ( CUdeviceptr* ptr, size_t size, size_t alignment, CUdeviceptr addr, unsigned long long flags ) 预留一段虚拟地址空间。

  • ptr 返回的虚拟地址空间起始地址指针。
  • size 请求的虚拟地址区间大小。
  • alignment 请求的虚拟地址区间对齐要求。
  • addr 地址提示(可为 0,驱动会自动选择)。
  • flags 当前未使用,必须为 0。

该函数根据给定参数保留一段虚拟地址空间,并返回起始地址到 ptr。此 API 仅在支持 统一虚拟寻址(UVA) 的系统上可用。size 和 addr 参数必须是主机页大小(通常为 4KB)的整数倍;alignment 必须是 2 的幂,或为 0(表示默认对齐)。如果 addr 为 0,则驱动程序自动选择分配地址;如果非 0,则视为地址提示。

1.3 cuMemCreate

CUresult cuMemCreate ( CUmemGenericAllocationHandle* handle, size_t size, const CUmemAllocationProp* prop, unsigned long long flags ) 根据给定属性创建一个 CUDA 内存分配,并返回一个通用内存句柄。

  • handle 返回的通用内存句柄。所有对该分配的操作都通过此句柄执行。
  • size 请求的分配大小。
  • prop 描述要创建的分配属性的结构体。
  • flags 目前保留,必须为 0。

在由 prop 指定的目标设备上创建一段内存分配。此分配不会自动映射到任何设备或主机地址空间。创建的通用内存句柄可通过 cuMemMap 映射到调用进程的虚拟地址空间中。该句柄不能直接跨进程传递,若要共享,需通过 cuMemExportToShareableHandle 导出。 分配的大小必须是cuMemGetAllocationGranularity 返回的最小粒度(使用CU_MEM_ALLOC_GRANULARITY_MINIMUM)的整数倍。 要在 CPU 上创建内存分配:

  • 若不针对特定 NUMA 节点,设置 CUmemLocation::type = CU_MEM_LOCATION_TYPE_HOST;
  • 若针对特定 NUMA 节点,设置 CUmemLocation::type = CU_MEM_LOCATION_TYPE_HOST_NUMA 并指定 NUMA ID;
  • CUmemLocation::id 在 HOST 模式下会被忽略;
  • HOST 分配不可用于 IPC,CUmemAllocationProp::requestedHandleTypes 必须为 0,否则报错。

要支持 Fabric 共享内存(CU_MEM_HANDLE_TYPE_FABRIC),系统需满足:

  1. 驱动创建 /dev/nvidia-caps-imex-channels 设备并在 /proc/devices 中列出;
  2. 应用用户能访问至少一个 IMEX 通道文件。

IMEX 通道基于用户隔离:同一用户下的进程可共享内存,不同用户需不同通道。

通道文件路径为 /dev/nvidia-caps-imex-channels/channel*,可用 Linux mknod 命令手动创建,例如:

mknod /dev/nvidia-caps-imex-channels/channel0 c <major_number> 0

若 allocFlags.usage 包含 CU_MEM_CREATE_USAGE_TILE_POOL,则该内存分配仅用于稀疏 CUDA 数组或 mipmapped 数组的 tile 池。

1.4 cuMemMap

CUresult cuMemMap ( CUdeviceptr ptr, size_t size, size_t offset, CUmemGenericAllocationHandle handle, unsigned long long flags ) 把物理内存分配映射到预留的虚拟地址区间内。

  • ptr 要映射的虚拟地址起点(必须由 cuMemAddressReserve 保留)。
  • size 映射大小。
  • offset 物理内存句柄内的偏移(目前必须为 0)。
  • handle 物理内存分配句柄。
  • flags 保留字段,必须为 0。

handle表示的物理内存[offset, offset + size]映射到[ptr, ptr + size]。 ptr必须得是cuMemAddressReserve 预留出来的空间。size, offset必须是cuMemGetAllocationGranularity返回的最小粒度的整数倍。 如果 handle表示multicast object,则所有参数需满足由 cuMulticastGetGranularity 返回的粒度要求。 注:

  1. cuMemMap 仅执行“映射”操作,还需要调用 cuMemSetAccess 使该地址范围对设备可访问;
  2. 若 handle 是跨进程导入的,必须先 cuMemMap,再调用 cuMemSetAccess;
  3. cuMemMap 不能覆盖已有映射。

1.5 cuMemSetAccess

CUresult cuMemSetAccess ( CUdeviceptr ptr, size_t size, const CUmemAccessDesc* desc, size_t count ) 为指定VA区间设置访问权限,跨进程的时候就要调这个了。

  • ptr 虚拟地址区间起点。
  • size 虚拟地址区间长度。
  • desc 描述访问属性的 CUmemAccessDesc 数组。
  • count 表示desc 数组的元素数量。

对VA区间[ptr, ptr + size]设置在不同GPU上访问的权限。范围是 cuMemMap映射的完整区间。当CUmemAccessDesc::CUmemLocation::type是 CU_MEM_LOCATION_TYPE_HOST_NUMA,那么CUmemAccessDesc::CUmemLocation::id会被忽略。对于multicast object,这里的ptr和size需要和 cuMulticastGetGranularity 返回的最小粒度对齐。

1.6 cuMemExportToShareableHandle and cuMemImportFromShareableHandle

CUresult cuMemExportToShareableHandle ( void* shareableHandle, CUmemGenericAllocationHandle handle, CUmemAllocationHandleType handleType, unsigned long long flags ) 将 CUDA 内存分配导出为可共享句柄,以便其他进程导入使用。

  • shareableHandle 存储导出后共享句柄的内存地址。
  • handle 要导出的 CUDA 内存句柄。
  • handleType 共享句柄类型(定义输出参数的类型与大小)。
  1. 根据给定的 CUDA 内存句柄,生成一个可跨进程共享的句柄。
  2. 接收方进程可使用 cuMemImportFromShareableHandle 将其重新导入为 CUDA 内存句柄,再使用 cuMemMap 进行映射。
  3. 共享句柄的具体实现和传递方式取决于 handleType。
  4. 当所有共享句柄被关闭且原始分配被释放后,内存将归还操作系统。之后继续使用该 CUDA 句柄将导致未定义行为。该 API 可与 Vulkan、OpenGL 等图形 API 配合,用于导入共享内存。

CUresult cuMemImportFromShareableHandle ( CUmemGenericAllocationHandle* handle, void* osHandle, CUmemAllocationHandleType shHandleType ) 用共享handle导入一个CUDA内存分配。

  • handle 返回的 CUDA 内存句柄。
  • osHandle 表示要导入的共享内存分配的操作系统句柄。
  • shHandleType 导出句柄的类型(对应导出时的 handleType)。

把另一个progress的shared handle变成自己的CUDA内存handle。若 shHandleType 为 CU_MEM_HANDLE_TYPE_FABRIC 且导入者进程没有访问相同 IMEX 通道的权限,则返回 CUDA_ERROR_NOT_PERMITTED。 此外,不保证同一个共享句柄在不同进程中得到的 CUDA handle 值相同。

1.7 cuMemRetainAllocationHandle

CUresult cuMemRetainAllocationHandle ( CUmemGenericAllocationHandle* handle, void* addr ) 之前映射过的地址VA地址(addr),返回对应的 CUDA 内存句柄(handle)。

1.8 cuMemMapArrayAsync

在 GPU 上异步执行映射(map)或取消映射(unmap)操作,作用于稀疏 CUDA 数组(Sparse CUDA Arrays)和稀疏多级 Mipmapped 数组。貌似我用不着。

1.9 cuMemUnmap, cuMemRelease, cuMemAddressFree

CUresult cuMemUnmap( CUdeviceptr ptr, size_t size ) 取消指定虚拟地址区间的物理内存映射。

  • ptr 要取消映射的虚拟地址起点。
  • size 区间大小。

CUresult cuMemRelease( CUmemGenericAllocationHandle handle ) 释放由 cuMemCreate 创建的内存句柄。

CUresult cuMemAddressFree (CUdeviceptr ptr, size_t size) 释放由 cuMemAddressReserve 预留的虚拟地址区间。size 必须与原始保留时的大小完全匹配,ptr 必须等于 cuMemAddressReserve 返回的地址。