6.14. 虚拟内存管理

本节介绍低级CUDA驱动程序应用程序编程接口的虚拟内存管理功能。

Functions

CUresult cuMemAddressFree ( CUdeviceptr ptr, size_t size )
Free an address range reservation.
CUresult cuMemAddressReserve ( CUdeviceptr* ptr, size_t size, size_t alignment, CUdeviceptr addr, unsigned long long flags )
Allocate an address range reservation.
CUresult cuMemCreate ( CUmemGenericAllocationHandle* handle, size_t size, const CUmemAllocationProp* prop, unsigned long long flags )
Create a CUDA memory handle representing a memory allocation of a given size described by the given properties.
CUresult cuMemExportToShareableHandle ( void* shareableHandle, CUmemGenericAllocationHandle handle, CUmemAllocationHandleType handleType, unsigned long long flags )
Exports an allocation to a requested shareable handle type.
CUresult cuMemGetAccess ( unsigned long long* flags, const CUmemLocation* location, CUdeviceptr ptr )
Get the access flags set for the given location and ptr.
CUresult cuMemGetAllocationGranularity ( size_t* granularity, const CUmemAllocationProp* prop, CUmemAllocationGranularity_flags option )
Calculates either the minimal or recommended granularity.
CUresult cuMemGetAllocationPropertiesFromHandle ( CUmemAllocationProp* prop, CUmemGenericAllocationHandle handle )
Retrieve the contents of the property structure defining properties for this handle.
CUresult cuMemImportFromShareableHandle ( CUmemGenericAllocationHandle* handle, void* osHandle, CUmemAllocationHandleType shHandleType )
Imports an allocation from a requested shareable handle type.
CUresult cuMemMap ( CUdeviceptr ptr, size_t size, size_t offset, CUmemGenericAllocationHandle handle, unsigned long long flags )
Maps an allocation handle to a reserved virtual address range.
CUresult cuMemMapArrayAsync ( CUarrayMapInfo* mapInfoList, unsigned int  count, CUstream hStream )
Maps or unmaps subregions of sparse CUDA arrays and sparse CUDA mipmapped arrays.
CUresult cuMemRelease ( CUmemGenericAllocationHandle handle )
Release a memory handle representing a memory allocation which was previously allocated through cuMemCreate.
CUresult cuMemRetainAllocationHandle ( CUmemGenericAllocationHandle* handle, void* addr )
Given an address addr, returns the allocation handle of the backing memory allocation.
CUresult cuMemSetAccess ( CUdeviceptr ptr, size_t size, const CUmemAccessDesc* desc, size_t count )
Set the access flags for each location specified in desc for the given virtual address range.
CUresult cuMemUnmap ( CUdeviceptr ptr, size_t size )
Unmap the backing memory of a given address range.

Functions

CUresult cuMemAddressFree ( CUdeviceptr ptr, size_t size )
释放一个地址范围预留。
参数
ptr
- Starting address of the virtual address range to free
size
- Size of the virtual address region to free
描述

释放由cuMemAddressReserve保留的虚拟地址范围。大小必须与memAddressReserve给定的值匹配,并且提供的ptr必须与memAddressReserve返回的值匹配。

另请参阅:

cuMemAddressReserve

CUresult cuMemAddressReserve ( CUdeviceptr* ptr, size_t size, size_t alignment, CUdeviceptr addr, unsigned long long flags )
分配一个地址范围预留。
参数
ptr
- Resulting pointer to start of virtual address range allocated
size
- Size of the reserved virtual address range requested
alignment
- Alignment of the reserved virtual address range requested
addr
- Fixed starting address range requested
flags
- Currently unused, must be zero
描述

根据给定参数保留一个虚拟地址范围,并在ptr中返回该范围的起始地址。此API要求系统支持UVA。大小和地址参数必须是主机页面大小的倍数,对齐参数必须是2的幂次方或零(使用默认对齐方式)。

另请参阅:

cuMemAddressFree

CUresult cuMemCreate ( CUmemGenericAllocationHandle* handle, size_t size, const CUmemAllocationProp* prop, unsigned long long flags )
创建一个CUDA内存句柄,表示由给定属性描述的指定大小的内存分配。
参数
handle
- Value of handle returned. All operations on this allocation are to be performed using this handle.
size
- Size of the allocation requested
prop
- Properties of the allocation to create.
flags
- flags for future use, must be zero now.
描述

这会在通过prop结构指定的目标设备上创建内存分配。所创建的分配将不具有任何设备或主机映射。该分配的通用内存handle可以通过cuMemMap映射到调用进程的地址空间。此句柄不能直接传输到其他进程(参见cuMemExportToShareableHandle)。在Windows上,调用者还必须在prop中传递一个LPSECURITYATTRIBUTE,以与此句柄关联,从而限制或允许接收进程访问此句柄(更多信息请参见CUmemAllocationProp::win32HandleMetaData)。此分配的size必须是使用CU_MEM_ALLOC_GRANULARITY_MINIMUM标志通过cuMemGetAllocationGranularity给出的值的倍数。要创建针对特定主机NUMA节点的CPU分配,应用程序必须将CUmemAllocationProp::CUmemLocation::type设置为CU_MEM_LOCATION_TYPE_HOST_NUMA,并且CUmemAllocationProp::CUmemLocation::id必须指定CPU的NUMA ID。在NUMA不可用的系统上,CUmemAllocationProp::CUmemLocation::id必须设置为0。将CU_MEM_LOCATION_TYPE_HOST_NUMA_CURRENTCU_MEM_LOCATION_TYPE_HOST指定为CUmemLocation::type将导致CUDA_ERROR_INVALID_VALUE

打算使用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`

如果CUmemAllocationProp::allocFlags::usage包含CU_MEM_CREATE_USAGE_TILE_POOL标志,则该内存分配仅用作稀疏CUDA数组和稀疏CUDA多级渐远纹理数组的底层图块池。(参见cuMemMapArrayAsync)。

Note:

请注意,此函数也可能返回之前异步启动的错误代码。

另请参阅:

cuMemRelease, cuMemExportToShareableHandle, cuMemImportFromShareableHandle

CUresult cuMemExportToShareableHandle ( void* shareableHandle, CUmemGenericAllocationHandle handle, CUmemAllocationHandleType handleType, unsigned long long flags )
将分配导出为请求的可共享句柄类型。
参数
shareableHandle
- Pointer to the location in which to store the requested handle type
handle
- CUDA handle for the memory allocation
handleType
- Type of shareable handle requested (defines type and size of the shareableHandle output parameter)
flags
- Reserved, must be zero
描述

给定一个CUDA内存句柄,创建一个可共享的内存分配句柄,该句柄可用于与其他进程共享内存。 接收方进程可以使用cuMemImportFromShareableHandle将可共享句柄转换回CUDA内存句柄,并使用cuMemMap进行映射。该句柄的具体实现形式及传输方式由handleType中请求的句柄类型定义。

一旦所有可共享的句柄被关闭且分配被释放,所引用的已分配内存将归还给操作系统,之后使用CUDA句柄将导致未定义行为。

该API还可与其他支持从共享类型导入内存的API(如Vulkan、OpenGL)结合使用

另请参阅:

cuMemImportFromShareableHandle

CUresult cuMemGetAccess ( unsigned long long* flags, const CUmemLocation* location, CUdeviceptr ptr )
Get the access flags set for the given location and ptr.
参数
flags
- Flags set for this location
location
- Location in which to check the flags for
ptr
- Address in which to check the access flags for
描述

另请参阅:

cuMemSetAccess

CUresult cuMemGetAllocationGranularity ( size_t* granularity, const CUmemAllocationProp* prop, CUmemAllocationGranularity_flags option )
计算最小或推荐的粒度。
参数
granularity
Returned granularity.
prop
Property for which to determine the granularity for
option
Determines which granularity to return
描述

根据给定的分配规格计算最小或推荐的粒度,并以粒度形式返回。 该粒度可用作对齐、大小或地址映射的倍数。

另请参阅:

cuMemCreate, cuMemMap

CUresult cuMemGetAllocationPropertiesFromHandle ( CUmemAllocationProp* prop, CUmemGenericAllocationHandle handle )
获取定义此句柄属性的属性结构内容。
参数
prop
- Pointer to a properties structure which will hold the information about this handle
handle
- Handle which to perform the query on
CUresult cuMemImportFromShareableHandle ( CUmemGenericAllocationHandle* handle, void* osHandle, CUmemAllocationHandleType shHandleType )
从请求的可共享句柄类型导入分配。
参数
handle
- CUDA Memory handle for the memory allocation.
osHandle
- Shareable Handle representing the memory allocation that is to be imported.
shHandleType
- handle type of the exported handle CUmemAllocationHandleType.
描述

如果当前进程不支持此共享句柄所描述的内存,此API将报错为CUDA_ERROR_NOT_SUPPORTED

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

Note:

从SLI组下设备创建的某些图形API(如Vulkan、OpenGL等)导出的可共享句柄可能不支持导入,因此该API将返回CUDA_ERROR_NOT_SUPPORTED。不能保证对于相同的给定操作系统可共享句柄,handle的内容会是相同的CUDA内存句柄,或者相同的底层分配。

另请参阅:

cuMemExportToShareableHandle, cuMemMap, cuMemRelease

CUresult cuMemMap ( CUdeviceptr ptr, size_t size, size_t offset, CUmemGenericAllocationHandle handle, unsigned long long flags )
将分配句柄映射到保留的虚拟地址范围。
参数
ptr
- Address where memory will be mapped.
size
- Size of the memory mapping.
offset
- Offset into the memory represented by
  • handle 开始映射的句柄
  • 注意:当前必须为零。
handle
- Handle to a shareable memory
flags
- flags for future use, must be zero now.
描述

将从字节offset开始、大小为sizehandle所表示的内存映射到地址范围[addr, addr + size]。该范围必须是先前通过cuMemAddressReserve保留的地址预留,且offset + size必须小于内存分配的大小。ptrsizeoffset都必须是使用cuMemGetAllocationGranularity配合CU_MEM_ALLOC_GRANULARITY_MINIMUM标志返回值的倍数。如果handle表示多播对象,则ptrsizeoffset必须对齐到使用CU_MULTICAST_MINIMUM_GRANULARITY标志调用cuMulticastGetGranularity返回的值。但为了获得最佳性能,建议将ptrsizeoffset对齐到使用CU_MULTICAST_RECOMMENDED_GRANULARITY标志调用cuMulticastGetGranularity返回的值。

请注意调用cuMemMap并不会使地址可访问,调用者需要通过调用cuMemSetAccess来更新连续映射的虚拟地址范围的可访问性。

当接收方进程从cuMemImportFromShareableHandle获取可共享内存句柄后,该进程必须使用cuMemMap将内存映射到其地址范围,然后才能通过cuMemSetAccess设置访问权限。

cuMemMap 只能在当前未被映射的虚拟地址范围预留上创建映射。

Note:

请注意,此函数也可能返回之前异步启动的错误代码。

另请参阅:

cuMemUnmap, cuMemSetAccess, cuMemCreate, cuMemAddressReserve, cuMemImportFromShareableHandle

CUresult cuMemMapArrayAsync ( CUarrayMapInfo* mapInfoList, unsigned int  count, CUstream hStream )
映射或取消映射稀疏CUDA数组和稀疏CUDA多级渐远纹理数组的子区域。
参数
mapInfoList
- List of CUarrayMapInfo
count
- Count of CUarrayMapInfo in mapInfoList
hStream
- Stream identifier for the stream to use for map or unmap operations
描述

对稀疏CUDA数组和稀疏CUDA多级渐远纹理数组的子区域执行映射或取消映射操作。每个操作由大小为countmapInfoList数组中的CUarrayMapInfo条目指定。CUarrayMapInfo结构定义如下:

‎     typedef struct CUarrayMapInfo_st {
              CUresourcetype resourceType;                   
              union {
                  CUmipmappedArray mipmap;
                  CUarray array;
              } resource;
      
              CUarraySparseSubresourceType subresourceType;   
              union {
                  struct {
                      unsigned int level;                     
                      unsigned int layer;                     
                      unsigned int offsetX;                   
                      unsigned int offsetY;                   
                      unsigned int offsetZ;                   
                      unsigned int extentWidth;               
                      unsigned int extentHeight;              
                      unsigned int extentDepth;               
                  } sparseLevel;
                  struct {
                      unsigned int layer;
                      unsigned long long offset;              
                      unsigned long long size;                
                  } miptail;
              } subresource;
      
              CUmemOperationType memOperationType;
              
              CUmemHandleType memHandleType;                  
              union {
                  CUmemGenericAllocationHandle memHandle;
              } memHandle;
      
              unsigned long long offset;                      
              unsigned int deviceBitMask;                     
              unsigned int flags;                             
              unsigned int reserved[2];                       
          } CUarrayMapInfo;

其中CUarrayMapInfo::resourceType指定要操作的资源类型。如果CUarrayMapInfo::resourceType设置为CUresourcetype::CU_RESOURCE_TYPE_ARRAY,则必须将CUarrayMapInfo::resource::array设置为有效的稀疏CUDA数组句柄。该CUDA数组必须是2D、2D分层或3D CUDA数组,并且必须使用带有CUDA_ARRAY3D_SPARSECUDA_ARRAY3D_DEFERRED_MAPPING标志的cuArrayCreatecuArray3DCreate进行分配。对于使用cuMipmappedArrayGetLevel获取的CUDA数组,将返回CUDA_ERROR_INVALID_VALUE。如果CUarrayMapInfo::resourceType设置为CUresourcetype::CU_RESOURCE_TYPE_MIPMAPPED_ARRAY,则必须将CUarrayMapInfo::resource::mipmap设置为有效的稀疏CUDA多级渐远纹理数组句柄。该CUDA多级渐远纹理数组必须是2D、2D分层或3D CUDA多级渐远纹理数组,并且必须使用带有CUDA_ARRAY3D_SPARSECUDA_ARRAY3D_DEFERRED_MAPPING标志的cuMipmappedArrayCreate进行分配。

CUarrayMapInfo::subresourceType 指定资源中子资源的类型。CUarraySparseSubresourceType_enum 定义为:

‎    typedef enum CUarraySparseSubresourceType_enum {
              CU_ARRAY_SPARSE_SUBRESOURCE_TYPE_SPARSE_LEVEL = 0,
              CU_ARRAY_SPARSE_SUBRESOURCE_TYPE_MIPTAIL = 1
          } CUarraySparseSubresourceType;

其中 CUarraySparseSubresourceType::CU_ARRAY_SPARSE_SUBRESOURCE_TYPE_SPARSE_LEVEL 表示稀疏mip层级,该层级在每个维度上至少跨越一个图块。其余因尺寸过小而在任何维度上都无法跨越至少一个图块的mip层级,构成了由 CUarraySparseSubresourceType::CU_ARRAY_SPARSE_SUBRESOURCE_TYPE_MIPTAIL 子资源类型指示的mip尾部区域。

如果CUarrayMapInfo::subresourceType设置为CUarraySparseSubresourceType::CU_ARRAY_SPARSE_SUBRESOURCE_TYPE_SPARSE_LEVEL,那么CUarrayMapInfo::subresource::sparseLevel 结构体必须包含有效的数组子区域偏移量和范围。CUarrayMapInfo::subresource::sparseLevel::offsetX、CUarrayMapInfo::subresource::sparseLevel::offsetY 和CUarrayMapInfo::subresource::sparseLevel::offsetZ必须分别指定有效的X、Y和Z偏移量。CUarrayMapInfo::subresource::sparseLevel::extentWidth、 CUarrayMapInfo::subresource::sparseLevel::extentHeight和CUarrayMapInfo::subresource::sparseLevel::extentDepth必须分别指定 有效的宽度、高度和深度范围。这些偏移量和范围必须与相应的平铺维度对齐。 对于CUDA多级渐远纹理数组,CUarrayMapInfo::subresource::sparseLevel::level必须指定有效的mip级别索引。否则, 必须为零。对于分层的CUDA数组和分层的CUDA多级渐远纹理数组,CUarrayMapInfo::subresource::sparseLevel::layer必须 指定有效的层索引。否则,必须为零。对于2D和2D分层的CUDA数组以及CUDA多级渐远纹理数组,CUarrayMapInfo::subresource::sparseLevel::offsetZ必须为零,且CUarrayMapInfo::subresource::sparseLevel::extentDepth 必须设置为1。可以通过调用cuArrayGetSparsePropertiescuMipmappedArrayGetSparseProperties获取平铺范围。

如果CUarrayMapInfo::subresourceType设置为CUarraySparseSubresourceType::CU_ARRAY_SPARSE_SUBRESOURCE_TYPE_MIPTAIL,那么CUarrayMapInfo::subresource::miptail 结构体必须在CUarrayMapInfo::subresource::miptail::offset中包含有效的mip尾偏移量,在CUarrayMapInfo::subresource::miptail::size中包含大小。 mip尾偏移量和mip尾大小都必须与图块大小对齐。对于没有在CUDA_ARRAY_SPARSE_PROPERTIES::flags中设置CU_ARRAY_SPARSE_PROPERTIES_SINGLE_MIPTAIL标志的分层CUDA mipmapped数组(由cuMipmappedArrayGetSparseProperties返回),CUarrayMapInfo::subresource::miptail::layer必须指定有效的层索引。否则,必须为零。

如果CUarrayMapInfo::resource::array或CUarrayMapInfo::resource::mipmap创建时设置了CUDA_ARRAY3D_DEFERRED_MAPPING标志,则CUarrayMapInfo::subresourceType和CUarrayMapInfo::subresource的内容将被忽略。

CUarrayMapInfo::memOperationType 指定操作类型。CUmemOperationType 定义为:

‎    typedef enum CUmemOperationType_enum {
              CU_MEM_OPERATION_TYPE_MAP = 1,
              CU_MEM_OPERATION_TYPE_UNMAP = 2
          } CUmemOperationType;
If CUarrayMapInfo::memOperationType is set to CUmemOperationType::CU_MEM_OPERATION_TYPE_MAP then the subresource will be mapped onto the tile pool memory specified by CUarrayMapInfo::memHandle at offset CUarrayMapInfo::offset. The tile pool allocation has to be created by specifying the CU_MEM_CREATE_USAGE_TILE_POOL flag when calling cuMemCreate. Also, CUarrayMapInfo::memHandleType must be set to CUmemHandleType::CU_MEM_HANDLE_TYPE_GENERIC.

如果CUarrayMapInfo::memOperationType设置为CUmemOperationType::CU_MEM_OPERATION_TYPE_UNMAP,则执行取消映射操作。此时CUarrayMapInfo::memHandle必须为NULL。

CUarrayMapInfo::deviceBitMask 指定必须映射或取消映射物理内存的设备列表。当前,此掩码必须仅设置一个位,且对应的设备必须与流关联的设备匹配。如果CUarrayMapInfo::memOperationType设置为CUmemOperationType::CU_MEM_OPERATION_TYPE_MAP,该设备还必须与CUarrayMapInfo::memHandle指定的瓦片池内存分配关联的设备匹配。

CUarrayMapInfo::flagsCUarrayMapInfo::reserved[] 未被使用,必须设置为零。

另请参阅:

cuMipmappedArrayCreate, cuArrayCreate, cuArray3DCreate, cuMemCreate, cuArrayGetSparseProperties, cuMipmappedArrayGetSparseProperties

CUresult cuMemRelease ( CUmemGenericAllocationHandle handle )
释放一个表示内存分配的内存句柄,该内存分配之前是通过cuMemCreate分配的。
参数
handle
Value of handle which was returned previously by cuMemCreate.
描述

释放通过cuMemCreate在设备上分配的内存。

当所有对该内存的未完成映射被解除映射,并且对该句柄(包括其可共享对应项)的所有未完成引用也被释放时,内存分配将被释放。即使存在使用该句柄创建的未完成映射,通用内存句柄也可以被释放。每次接收进程导入可共享句柄时,都需要将其与cuMemRelease配对使用才能释放该句柄。如果handle不是有效句柄,则行为未定义。

Note:

请注意,此函数也可能返回之前异步启动的错误代码。

另请参阅:

cuMemCreate

CUresult cuMemRetainAllocationHandle ( CUmemGenericAllocationHandle* handle, void* addr )
Given an address addr, returns the allocation handle of the backing memory allocation.
参数
handle
CUDA Memory handle for the backing memory allocation.
addr
Memory address to query, that has been mapped previously.
描述

该句柄保证与用于映射内存的句柄值相同。如果请求的地址未被映射,该函数将执行失败。返回的句柄必须通过相应次数的cuMemRelease调用来释放。

Note:

地址 addr 可以是之前通过 cuMemMap 映射范围内的任意地址,不一定是起始地址。

另请参阅:

cuMemCreate, cuMemRelease, cuMemMap

CUresult cuMemSetAccess ( CUdeviceptr ptr, size_t size, const CUmemAccessDesc* desc, size_t count )
Set the access flags for each location specified in desc for the given virtual address range.
参数
ptr
- Starting address for the virtual address range
size
- Length of the virtual address range
desc
- Array of CUmemAccessDesc that describe how to change the
  • 为每个指定位置进行映射
count
- Number of CUmemAccessDesc in desc
描述

通过ptrsize给定的虚拟地址范围,以及desccount指定的数组位置,为目标位置设置访问标志。该范围必须是一个完全映射的地址范围,包含所有由cuMemMap/cuMemCreate创建的分配。用户不能为在其他位置类型上创建的分配指定CU_MEM_LOCATION_TYPE_HOST_NUMA可访问性。注意:当CUmemAccessDesc::CUmemLocation::type为CU_MEM_LOCATION_TYPE_HOST_NUMA时,CUmemAccessDesc::CUmemLocation::id将被忽略。当为映射多播对象的虚拟地址范围设置访问标志时,ptrsize必须对齐到使用CU_MULTICAST_MINIMUM_GRANULARITY标志调用cuMulticastGetGranularity返回的值。但为了获得最佳性能,建议将ptrsize对齐到使用CU_MULTICAST_RECOMMENDED_GRANULARITY标志调用cuMulticastGetGranularity返回的值。

Note:
  • 请注意,此函数也可能返回之前异步启动的错误代码。

  • 该函数在大多数使用场景下表现出同步行为。

另请参阅:

cuMemSetAccess, cuMemCreate, :cuMemMap

CUresult cuMemUnmap ( CUdeviceptr ptr, size_t size )
解除给定地址范围的底层内存映射。
参数
ptr
- Starting address for the virtual address range to unmap
size
- Size of the virtual address range to unmap
描述

地址范围必须是映射的整个连续地址范围。换句话说,cuMemUnmap不能取消映射由cuMemCreate/cuMemMap映射的地址范围的子范围。如果不存在现有映射且没有未释放的内存句柄,任何后备内存分配都将被释放。

cuMemUnmap成功返回时,地址范围将被转换为地址保留区,可用于后续调用cuMemMap。任何对该虚拟地址的新映射都需要通过cuMemSetAccess授予访问权限,因为所有映射初始时都没有设置可访问性。

Note:
  • 请注意,此函数也可能返回之前异步启动的错误代码。

  • 该函数在大多数使用场景下表现出同步行为。

另请参阅:

cuMemCreate, cuMemAddressReserve