6.13. 流序内存分配器

概述

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

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

支持的平台

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

Functions

__host__cudaError_t cudaFreeAsync ( void* devPtr, cudaStream_t hStream )
Frees memory with stream ordered semantics.
__host__cudaError_t cudaMallocAsync ( void** devPtr, size_t size, cudaStream_t hStream )
Allocates memory with stream ordered semantics.
__host__cudaError_t cudaMallocFromPoolAsync ( void** ptr, size_t size, cudaMemPool_t memPool, cudaStream_t stream )
Allocates memory from a specified pool with stream ordered semantics.
__host__cudaError_t cudaMemPoolCreate ( cudaMemPool_t* memPool, const cudaMemPoolProps* poolProps )
Creates a memory pool.
__host__cudaError_t cudaMemPoolDestroy ( cudaMemPool_t memPool )
Destroys the specified memory pool.
__host__cudaError_t cudaMemPoolExportPointer ( cudaMemPoolPtrExportData* exportData, void* ptr )
Export data to share a memory pool allocation between processes.
__host__cudaError_t cudaMemPoolExportToShareableHandle ( void* shareableHandle, cudaMemPool_t memPool, cudaMemAllocationHandleType handleType, unsigned int  flags )
Exports a memory pool to the requested handle type.
__host__cudaError_t cudaMemPoolGetAccess ( cudaMemAccessFlags ** flags, cudaMemPool_t memPool, cudaMemLocation* location )
Returns the accessibility of a pool from a device.
__host__cudaError_t cudaMemPoolGetAttribute ( cudaMemPool_t memPool, cudaMemPoolAttr attr, void* value )
Gets attributes of a memory pool.
__host__cudaError_t cudaMemPoolImportFromShareableHandle ( cudaMemPool_t* memPool, void* shareableHandle, cudaMemAllocationHandleType handleType, unsigned int  flags )
imports a memory pool from a shared handle.
__host__cudaError_t cudaMemPoolImportPointer ( void** ptr, cudaMemPool_t memPool, cudaMemPoolPtrExportData* exportData )
Import a memory pool allocation from another process.
__host__cudaError_t cudaMemPoolSetAccess ( cudaMemPool_t memPool, const cudaMemAccessDesc* descList, size_t count )
Controls visibility of pools between devices.
__host__cudaError_t cudaMemPoolSetAttribute ( cudaMemPool_t memPool, cudaMemPoolAttr attr, void* value )
Sets attributes of a memory pool.
__host__cudaError_t cudaMemPoolTrimTo ( cudaMemPool_t memPool, size_t minBytesToKeep )
Tries to release memory back to the OS.

Functions

__host__cudaError_t cudaFreeAsync ( void* devPtr, cudaStream_t hStream )
使用流顺序语义释放内存。
参数
devPtr
hStream
- The stream establishing the stream ordering promise
描述

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

Note:

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

Note:

另请参阅:

cuMemFreeAsync, cudaMallocAsync

__host__cudaError_t cudaMallocAsync ( void** devPtr, size_t size, cudaStream_t hStream )
使用流顺序语义分配内存。
参数
devPtr
- Returned device pointer
size
- Number of bytes to allocate
hStream
- The stream establishing the stream ordering contract and the memory pool to allocate from
返回

cudaSuccess, cudaErrorInvalidValue, cudaErrorNotSupported, cudaErrorOutOfMemory,

描述

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

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

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

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

Note:

另请参阅:

cuMemAllocAsync, cudaMallocAsync ( C++ API), cudaMallocFromPoolAsync, cudaFreeAsync, cudaDeviceSetMemPool, cudaDeviceGetDefaultMemPool, cudaDeviceGetMemPool, cudaMemPoolSetAccess, cudaMemPoolSetAttribute, cudaMemPoolGetAttribute

__host__cudaError_t cudaMallocFromPoolAsync ( void** ptr, size_t size, cudaMemPool_t memPool, cudaStream_t stream )
从指定内存池中分配内存,遵循流顺序语义。
参数
ptr
- Returned device pointer
size
memPool
- The pool to allocate from
stream
- The stream establishing the stream ordering semantic
描述

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

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

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

Note:

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

另请参阅:

cuMemAllocFromPoolAsync, cudaMallocAsync ( C++ API), cudaMallocAsync, cudaFreeAsync, cudaDeviceGetDefaultMemPool, cudaMemPoolCreate, cudaMemPoolSetAccess, cudaMemPoolSetAttribute

__host__cudaError_t cudaMemPoolCreate ( cudaMemPool_t* memPool, const cudaMemPoolProps* poolProps )
创建一个内存池。
描述

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

要创建针对特定主机NUMA节点的内存池,应用程序必须将cudaMemPoolProps::cudaMemLocation::type 设置为cudaMemLocationTypeHostNuma,且cudaMemPoolProps::cudaMemLocation::id必须指定主机内存节点的NUMA ID。若将cudaMemLocationTypeHostNumaCurrentcudaMemLocationTypeHost指定为cudaMemPoolProps::cudaMemLocation::type,将导致cudaErrorInvalidValue错误。默认情况下,内存池的内存可从分配它的设备访问。对于使用cudaMemLocationTypeHostNuma创建的池,其默认可访问性将来自主机CPU。应用程序可通过为cudaMemPoolProps::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:

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

另请参阅:

cuMemPoolCreate, cudaDeviceSetMemPool, cudaMallocFromPoolAsync, cudaMemPoolExportToShareableHandle, cudaDeviceGetDefaultMemPool, cudaDeviceGetMemPool

__host__cudaError_t cudaMemPoolDestroy ( cudaMemPool_t memPool )
销毁指定的内存池。
描述

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

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

Note:

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

另请参阅:

cuMemPoolDestroy, cudaFreeAsync, cudaDeviceSetMemPool, cudaDeviceGetDefaultMemPool, cudaDeviceGetMemPool, cudaMemPoolCreate

__host__cudaError_t cudaMemPoolExportPointer ( cudaMemPoolPtrExportData* exportData, void* ptr )
导出数据以在进程间共享内存池分配。
参数
exportData
ptr
- pointer to memory being exported
返回

cudaSuccess, cudaErrorInvalidValue, cudaErrorOutOfMemory

描述

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

另请参阅:

cuMemPoolExportPointer, cudaMemPoolExportToShareableHandle, cudaMemPoolImportFromShareableHandle, cudaMemPoolImportPointer

__host__cudaError_t cudaMemPoolExportToShareableHandle ( void* shareableHandle, cudaMemPool_t memPool, cudaMemAllocationHandleType handleType, unsigned int  flags )
将内存池导出到请求的句柄类型。
参数
shareableHandle
memPool
handleType
- the type of handle to create
flags
- must be 0
返回

cudaSuccess, cudaErrorInvalidValue, cudaErrorOutOfMemory

描述

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

Note:

: 要创建一个支持IPC的内存池,需要使用除cudaMemHandleTypeNone之外的CUmemAllocationHandleType来创建内存池。

另请参阅:

cuMemPoolExportToShareableHandle, cudaMemPoolImportFromShareableHandle, cudaMemPoolExportPointer, cudaMemPoolImportPointer

__host__cudaError_t cudaMemPoolGetAccess ( cudaMemAccessFlags ** flags, cudaMemPool_t memPool, cudaMemLocation* location )
返回设备对池的可访问性。
参数
flags
- the accessibility of the pool from the specified location
memPool
- the pool being queried
location
- the location accessing the pool
描述

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

另请参阅:

cuMemPoolGetAccess, cudaMemPoolSetAccess

__host__cudaError_t cudaMemPoolGetAttribute ( cudaMemPool_t memPool, cudaMemPoolAttr attr, void* value )
获取内存池的属性。
参数
memPool
attr
- The attribute to get
value
- Retrieved value
描述

支持的属性包括:

Note:

请注意,根据cudaStreamAddCallback的规定,回调函数中不得调用任何CUDA函数。在这种情况下,cudaErrorNotPermitted可能会(但不保证)作为诊断错误返回。

另请参阅:

cuMemPoolGetAttribute, cudaMallocAsync, cudaFreeAsync, cudaDeviceGetDefaultMemPool, cudaDeviceGetMemPool, cudaMemPoolCreate

__host__cudaError_t cudaMemPoolImportFromShareableHandle ( cudaMemPool_t* memPool, void* shareableHandle, cudaMemAllocationHandleType handleType, unsigned int  flags )
从共享句柄导入内存池。
参数
memPool
shareableHandle
handleType
- The type of handle being imported
flags
- must be 0
返回

cudaSuccess, cudaErrorInvalidValue, cudaErrorOutOfMemory

描述

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

Note:

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

另请参阅:

cuMemPoolImportFromShareableHandle, cudaMemPoolExportToShareableHandle, cudaMemPoolExportPointer, cudaMemPoolImportPointer

__host__cudaError_t cudaMemPoolImportPointer ( void** ptr, cudaMemPool_t memPool, cudaMemPoolPtrExportData* exportData )
从另一个进程导入内存池分配。
描述

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

Note:

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

另请参阅:

cuMemPoolImportPointer, cudaMemPoolExportToShareableHandle, cudaMemPoolImportFromShareableHandle, cudaMemPoolExportPointer

__host__cudaError_t cudaMemPoolSetAccess ( cudaMemPool_t memPool, const cudaMemAccessDesc* descList, size_t count )
控制设备间池的可见性。
参数
memPool
descList
count
- Number of descriptors in the map array.
__host__cudaError_t cudaMemPoolSetAttribute ( cudaMemPool_t memPool, cudaMemPoolAttr attr, void* value )
设置内存池的属性。
参数
memPool
attr
- The attribute to modify
value
- Pointer to the value to assign
描述

支持的属性包括:

  • cudaMemPoolAttrReleaseThreshold: (值类型 = cuuint64_t) 尝试将内存释放回操作系统之前保留的内存大小(以字节为单位)。 当内存池持有的内存超过释放阈值时,分配器将在下一次调用流、事件或上下文同步时尝试将内存释放回操作系统。(默认值为0)

  • cudaMemPoolReuseFollowEventDependencies: (值类型 = int) 允许cudaMallocAsync异步使用另一流中已释放的内存,只要分配流对释放操作存在流顺序依赖。CUDA事件和空流交互可以创建所需的流顺序依赖关系。(默认启用)

  • cudaMemPoolReuseAllowOpportunistic: (值类型 = int) 当释放操作与分配操作之间不存在依赖关系时,允许重用已完成的释放内存。(默认启用)

  • cudaMemPoolReuseAllowInternalDependencies: (值类型 = int) 允许cudaMallocAsync插入新的流依赖关系,以建立重用由cudaFreeAsync释放的内存块所需的流顺序(默认启用)。

  • cudaMemPoolAttrReservedMemHigh: (值类型 = cuuint64_t) 重置用于跟踪内存池分配的后备内存量的高水位标记。将此属性设置为非零值是非法操作。

  • cudaMemPoolAttrUsedMemHigh: (value type = cuuint64_t) 重置用于跟踪内存池已分配内存使用量的高水位标记。将此属性设置为非零值是无效的。

Note:

请注意,根据cudaStreamAddCallback的规定,回调函数中不得调用任何CUDA函数。在这种情况下,可能会(但不保证)返回cudaErrorNotPermitted作为诊断信息。

另请参阅:

cuMemPoolSetAttribute, cudaMallocAsync, cudaFreeAsync, cudaDeviceGetDefaultMemPool, cudaDeviceGetMemPool, cudaMemPoolCreate

__host__cudaError_t cudaMemPoolTrimTo ( cudaMemPool_t memPool, size_t minBytesToKeep )
尝试将内存释放回操作系统。
参数
memPool
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:
  • : 未释放的内存分配会被视为未完成。

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

Note:

请注意,根据cudaStreamAddCallback的规定,回调函数中不得调用任何CUDA函数。在这种情况下,cudaErrorNotPermitted可能会(但不保证)作为诊断信息返回。

另请参阅:

cuMemPoolTrimTo, cudaMallocAsync, cudaFreeAsync, cudaDeviceGetDefaultMemPool, cudaDeviceGetMemPool, cudaMemPoolCreate