6.15. 流序内存分配器

本节介绍由底层CUDA驱动程序应用程序编程接口提供的流序内存分配器。

概述

异步分配器允许用户按流顺序进行分配和释放操作。分配的所有异步访问必须发生在分配和释放的流执行之间。如果内存访问超出了承诺的流顺序范围,在分配前使用/释放后使用的错误将导致未定义行为。

只要分配器能够保证合规的内存访问在时间上不会重叠,它就可以自由地重新分配内存。在建立时间保证时,分配器可以参考内部流顺序以及流间依赖关系(如CUDA事件和空流依赖)。分配器还可以插入流间依赖关系以建立时间保证。

支持的平台

可以通过调用cuDeviceGetAttribute()并传入设备属性CU_DEVICE_ATTRIBUTE_MEMORY_POOLS_SUPPORTED来查询设备是否支持集成流顺序内存分配器

Functions

CUresult cuMemAllocAsync ( CUdeviceptr* dptr, size_t bytesize, CUstream hStream )
Allocates memory with stream ordered semantics.
CUresult cuMemAllocFromPoolAsync ( CUdeviceptr* dptr, size_t bytesize, CUmemoryPool pool, CUstream hStream )
Allocates memory from a specified pool with stream ordered semantics.
CUresult cuMemFreeAsync ( CUdeviceptr dptr, CUstream hStream )
Frees memory with stream ordered semantics.
CUresult cuMemPoolCreate ( CUmemoryPool* pool, const CUmemPoolProps* poolProps )
Creates a memory pool.
CUresult cuMemPoolDestroy ( CUmemoryPool pool )
Destroys the specified memory pool.
CUresult cuMemPoolExportPointer ( CUmemPoolPtrExportData* shareData_out, CUdeviceptr ptr )
Export data to share a memory pool allocation between processes.
CUresult cuMemPoolExportToShareableHandle ( void* handle_out, CUmemoryPool pool, CUmemAllocationHandleType handleType, unsigned long long flags )
Exports a memory pool to the requested handle type.
CUresult cuMemPoolGetAccess ( CUmemAccess_flags* flags, CUmemoryPool memPool, CUmemLocation* location )
Returns the accessibility of a pool from a device.
CUresult cuMemPoolGetAttribute ( CUmemoryPool pool, CUmemPool_attribute attr, void* value )
Gets attributes of a memory pool.
CUresult cuMemPoolImportFromShareableHandle ( CUmemoryPool* pool_out, void* handle, CUmemAllocationHandleType handleType, unsigned long long flags )
imports a memory pool from a shared handle.
CUresult cuMemPoolImportPointer ( CUdeviceptr* ptr_out, CUmemoryPool pool, CUmemPoolPtrExportData* shareData )
Import a memory pool allocation from another process.
CUresult cuMemPoolSetAccess ( CUmemoryPool pool, const CUmemAccessDesc* map, size_t count )
Controls visibility of pools between devices.
CUresult cuMemPoolSetAttribute ( CUmemoryPool pool, CUmemPool_attribute attr, void* value )
Sets attributes of a memory pool.
CUresult cuMemPoolTrimTo ( CUmemoryPool pool, size_t minBytesToKeep )
Tries to release memory back to the OS.

Functions

CUresult cuMemAllocAsync ( CUdeviceptr* dptr, size_t bytesize, CUstream hStream )
使用流顺序语义分配内存。
参数
dptr
- Returned device pointer
bytesize
- Number of bytes to allocate
hStream
- The stream establishing the stream ordering contract and the memory pool to allocate from
描述

hStream中插入一个内存分配操作。分配的内存指针会立即通过*dptr返回。在该分配操作完成之前,不能访问该分配的内存。分配的内存来自当前流设备的内存池。

Note:
  • 设备的默认内存池包含来自该设备的设备内存。

  • 基础的流顺序允许未来提交到同一流中的工作使用该分配。流查询、流同步以及CUDA事件可用于确保分配操作在单独流中提交的工作运行前完成。

  • 在流捕获期间,调用此函数会创建一个分配节点。此时,分配由图(graph)而非内存池拥有。内存池的属性用于设置该节点的创建参数。

另请参阅:

cuMemAllocFromPoolAsync, cuMemFreeAsync, cuDeviceSetMemPool, cuDeviceGetDefaultMemPool, cuDeviceGetMemPool, cuMemPoolCreate, cuMemPoolSetAccess, cuMemPoolSetAttribute

CUresult cuMemAllocFromPoolAsync ( CUdeviceptr* dptr, size_t bytesize, CUmemoryPool pool, CUstream hStream )
从指定内存池中分配内存,遵循流顺序语义。
参数
dptr
- Returned device pointer
bytesize
- Number of bytes to allocate
pool
- The pool to allocate from
hStream
- The stream establishing the stream ordering semantic
描述

hStream中插入一个分配操作。分配内存的指针会立即通过*dptr返回。在分配操作完成之前,不能访问该分配的内存。该分配来自指定的内存池。

Note:
  • 指定的内存池可能来自与指定hStream不同的设备。

  • 基础流顺序允许提交到同一流的未来工作使用该分配。流查询、流同步和CUDA事件可用于确保分配操作在单独流中提交的工作运行前完成。

Note:

在流捕获期间,此函数会导致创建一个分配节点。在这种情况下,分配由图(graph)拥有,而非内存池。内存池的属性用于设置该节点的创建参数。

另请参阅:

cuMemAllocAsync, cuMemFreeAsync, cuDeviceGetDefaultMemPool, cuDeviceGetMemPool, cuMemPoolCreate, cuMemPoolSetAccess, cuMemPoolSetAttribute

CUresult cuMemFreeAsync ( CUdeviceptr dptr, CUstream hStream )
使用流顺序语义释放内存。
参数
dptr
- memory to free
hStream
- The stream establishing the stream ordering contract.
描述

hStream中插入一个释放操作。在流执行到达该释放点后,不得再访问该分配内存。此API返回后,若从GPU上启动的任何后续工作中访问该内存或查询其指针属性,将导致未定义行为。

Note:

在流捕获过程中,此函数会导致创建一个自由节点,因此必须传递图分配的地址。

CUresult cuMemPoolCreate ( CUmemoryPool* pool, const CUmemPoolProps* poolProps )
创建一个内存池。
描述

创建一个CUDA内存池,并在pool中返回其句柄。poolProps参数决定了内存池的属性,例如支持设备和IPC功能。

要创建针对特定主机NUMA节点的内存池,应用程序必须将CUmemPoolProps::CUmemLocation::type设置为 CU_MEM_LOCATION_TYPE_HOST_NUMA,并且CUmemPoolProps::CUmemLocation::id必须指定主机内存节点的NUMA ID。若将CU_MEM_LOCATION_TYPE_HOST_NUMA_CURRENTCU_MEM_LOCATION_TYPE_HOST作为CUmemPoolProps::CUmemLocation::type的值,将导致CUDA_ERROR_INVALID_VALUE错误。默认情况下,内存池的内存可从分配它的设备访问。对于使用CU_MEM_LOCATION_TYPE_HOST_NUMA创建的池,其默认可访问性将来自主机CPU。应用程序可通过为 CUmemPoolProps::maxSize指定非零值来控制池的最大大小。如果设置为0,池的最大大小将默认为系统相关值。

打算使用CU_MEM_HANDLE_TYPE_FABRIC进行内存共享的应用程序必须确保:(1) 驱动程序已创建`nvidia-caps-imex-channels`字符设备,并在/proc/devices下列出 (2) 至少有一个IMEX通道文件可供启动应用程序的用户访问。

当导出器和导入器CUDA进程被授予访问同一IMEX通道的权限时,它们可以安全地共享内存。

IMEX通道安全模型基于每个用户运行。这意味着如果用户有权访问有效的IMEX通道,则该用户下的所有进程都可以共享内存。当需要多用户隔离时,每个用户都需要单独的IMEX通道。

这些通道文件位于/dev/nvidia-caps-imex-channels/channel*目录下,可以通过标准的操作系统原生调用(如Linux上的mknod)创建。例如:要使用/proc/devices中的主设备号创建channel0,用户可以执行以下命令: `mknod /dev/nvidia-caps-imex-channels/channel0 c =""> 0`

Note:

指定 CU_MEM_HANDLE_TYPE_NONE 将创建一个不支持 IPC 的内存池。

另请参阅:

cuDeviceSetMemPool, cuDeviceGetMemPool, cuDeviceGetDefaultMemPool, cuMemAllocFromPoolAsync, cuMemPoolExportToShareableHandle

CUresult cuMemPoolDestroy ( CUmemoryPool pool )
销毁指定的内存池。
描述

如果在调用cuMemPoolDestroy时,从该内存池获取的任何指针尚未释放,或者内存池中存在未完成的释放操作,该函数将立即返回,并且一旦没有未完成的分配,与内存池关联的资源将自动释放。

销毁设备的当前内存池会将该设备的默认内存池设置为该设备的当前内存池。

Note:

设备的默认内存池无法被销毁。

另请参阅:

cuMemFreeAsync, cuDeviceSetMemPool, cuDeviceGetMemPool, cuDeviceGetDefaultMemPool, cuMemPoolCreate

CUresult cuMemPoolExportPointer ( CUmemPoolPtrExportData* shareData_out, CUdeviceptr ptr )
导出数据以在进程间共享内存池分配。
参数
shareData_out
- Returned export data
ptr
- pointer to memory being exported
描述

构建shareData_out用于从已共享的内存池中共享特定分配。接收方进程可以通过cuMemPoolImportPointer API导入该分配。该数据不是句柄,可以通过任何IPC机制共享。

另请参阅:

cuMemPoolExportToShareableHandle, cuMemPoolImportFromShareableHandle, cuMemPoolImportPointer

CUresult cuMemPoolExportToShareableHandle ( void* handle_out, CUmemoryPool pool, CUmemAllocationHandleType handleType, unsigned long long flags )
将内存池导出到请求的句柄类型。
参数
handle_out
- Returned OS handle
pool
- pool to export
handleType
- the type of handle to create
flags
- must be 0
描述

给定一个支持IPC(进程间通信)的内存池,创建一个操作系统句柄以便与其他进程共享该内存池。接收方进程可以使用cuMemPoolImportFromShareableHandle将可共享句柄转换为内存池。然后可以通过cuMemPoolExportPointercuMemPoolImportPointer API共享单个指针。可共享句柄的具体实现及其传输方式由所请求的句柄类型定义。

Note:

要创建一个支持IPC的内存池,请使用除CU_MEM_HANDLE_TYPE_NONE之外的其他CUmemAllocationHandleType类型来创建内存池。

另请参阅:

cuMemPoolImportFromShareableHandle, cuMemPoolExportPointer, cuMemPoolImportPointer, cuMemAllocAsync, cuMemFreeAsync, cuDeviceGetDefaultMemPool, cuDeviceGetMemPool, cuMemPoolCreate, cuMemPoolSetAccess, cuMemPoolSetAttribute

CUresult cuMemPoolGetAccess ( CUmemAccess_flags* flags, CUmemoryPool memPool, CUmemLocation* location )
返回设备对池的可访问性。
参数
flags
- the accessibility of the pool from the specified location
memPool
- the pool being queried
location
- the location accessing the pool
描述

返回池内存从指定位置的可访问性。

另请参阅:

cuMemAllocAsync, cuMemFreeAsync, cuDeviceGetDefaultMemPool, cuDeviceGetMemPool, cuMemPoolCreate

CUresult cuMemPoolGetAttribute ( CUmemoryPool pool, CUmemPool_attribute attr, void* value )
获取内存池的属性。
参数
pool
- The memory pool to get attributes of
attr
- The attribute to get
value
- Retrieved value
描述

支持的属性包括:

另请参阅:

cuMemAllocAsync, cuMemFreeAsync, cuDeviceGetDefaultMemPool, cuDeviceGetMemPool, cuMemPoolCreate

CUresult cuMemPoolImportFromShareableHandle ( CUmemoryPool* pool_out, void* handle, CUmemAllocationHandleType handleType, unsigned long long flags )
从共享句柄导入内存池。
参数
pool_out
- Returned memory pool
handle
- OS handle of the pool to open
handleType
- The type of handle being imported
flags
- must be 0
描述

可以通过cuMemPoolImportPointer从导入池中导入特定的分配。

如果handleTypeCU_MEM_HANDLE_TYPE_FABRIC且导入进程未被授予与导出进程相同的IMEX通道访问权限,此API将报错为CUDA_ERROR_NOT_PERMITTED

Note:

导入的内存池不支持创建新的分配。因此,导入的内存池不能用于cuDeviceSetMemPool或cuMemAllocFromPoolAsync调用。

另请参阅:

cuMemPoolExportToShareableHandle, cuMemPoolExportPointer, cuMemPoolImportPointer

CUresult cuMemPoolImportPointer ( CUdeviceptr* ptr_out, CUmemoryPool pool, CUmemPoolPtrExportData* shareData )
从另一个进程导入内存池分配。
参数
ptr_out
- pointer to imported memory
pool
- pool from which to import
shareData
- data specifying the memory to import
描述

ptr_out中返回指向导入内存的指针。在导出进程完成分配操作之前,不得访问导入的内存。在导出进程中释放内存之前,必须从所有导入进程中释放该内存。该指针可以通过cuMemFree或cuMemFreeAsync释放。如果使用cuMemFreeAsync,则必须在导出进程执行释放操作之前,在导入进程上完成释放。

Note:

在导出过程中,只要导出进程中的cuMemFreeAsync指定了一个对导入进程的cuMemFreeAsync具有流依赖关系的流,就可以在cuMemFreeAsync操作在其流中完成之前使用cuMemFreeAsync API。

另请参阅:

cuMemPoolExportToShareableHandle, cuMemPoolImportFromShareableHandle, cuMemPoolExportPointer

CUresult cuMemPoolSetAccess ( CUmemoryPool pool, const CUmemAccessDesc* map, size_t count )
控制设备间池的可见性。
参数
pool
- The pool being modified
map
- Array of access descriptors. Each descriptor instructs the access to enable for a single gpu.
count
- Number of descriptors in the map array.
CUresult cuMemPoolSetAttribute ( CUmemoryPool pool, CUmemPool_attribute attr, void* value )
设置内存池的属性。
参数
pool
- The memory pool to modify
attr
- The attribute to modify
value
- Pointer to the value to assign
描述

支持的属性包括:

另请参阅:

cuMemAllocAsync, cuMemFreeAsync, cuDeviceGetDefaultMemPool, cuDeviceGetMemPool, cuMemPoolCreate

CUresult cuMemPoolTrimTo ( CUmemoryPool pool, size_t minBytesToKeep )
尝试将内存释放回操作系统。
参数
pool
- The memory pool to trim
minBytesToKeep
- If the pool has less than minBytesToKeep reserved, the TrimTo operation is a no-op. Otherwise the pool will be guaranteed to have at least minBytesToKeep bytes reserved after the operation.
描述

将内存释放回操作系统,直到内存池保留的字节数少于minBytesToKeep,或者分配器无法再安全释放更多内存为止。分配器无法释放支持未完成异步分配的OS分配。OS分配可能以与用户分配不同的粒度发生。

Note:
  • : 未释放的内存分配会被视为未完成。

  • : 已异步释放但主机尚未观察到其完成(例如通过同步操作)的分配仍可能被视为未完成。

另请参阅:

cuMemAllocAsync, cuMemFreeAsync, cuDeviceGetDefaultMemPool, cuDeviceGetMemPool, cuMemPoolCreate