6.17. 统一寻址
本节介绍低级别CUDA驱动程序应用程序编程接口的统一寻址功能。
概述
CUDA设备可以与主机共享统一地址空间。对于这些设备来说,设备指针和主机指针没有区别——相同的指针值既可用于主机程序访问内存,也可用于设备上运行的内核访问内存(以下列举的例外情况除外)。
支持的平台
可以通过调用cuDeviceGetAttribute()并传入设备属性CU_DEVICE_ATTRIBUTE_UNIFIED_ADDRESSING来查询设备是否支持统一寻址功能。
在64位进程中会自动启用统一寻址
从指针值查找信息
可以查询支持指针值的内存相关信息。例如,可能需要了解指针指向的是主机内存还是设备内存。另一个例子是,对于设备内存,可能需要知道该内存位于哪个CUDA设备上。这些属性可以通过函数cuPointerGetAttribute()进行查询。
由于指针是唯一的,因此无需向CUDA API中的各种复制函数指定有关指针的信息。函数cuMemcpy()可用于在两个指针之间执行复制操作,无需考虑它们指向的是主机内存还是设备内存(对于支持统一寻址的设备,使得cuMemcpyHtoD()、cuMemcpyDtoD()和cuMemcpyDtoH()变得不必要)。对于多维复制操作,可以使用内存类型CU_MEMORYTYPE_UNIFIED来指定CUDA驱动程序应从指针值推断其位置。
主机分配内存的自动映射
在所有上下文中使用cuMemAllocHost()和cuMemHostAlloc()分配的主机内存,始终可以直接被所有支持统一寻址设备的上下文访问。无论是否指定了CU_MEMHOSTALLOC_PORTABLE和CU_MEMHOSTALLOC_DEVICEMAP标志,情况都是如此。
通过支持统一寻址的所有设备上的内核访问已分配主机内存的指针值,与主机上访问该内存的指针值相同,因此无需调用cuMemHostGetDevicePointer()来获取这些分配的设备指针。
请注意,对于使用标志CU_MEMHOSTALLOC_WRITECOMBINED分配的内存情况并非如此,如下文所述。
对等内存自动注册
当从支持统一寻址的上下文中启用对另一个同样支持统一寻址的对等上下文的直接访问(通过cuCtxEnablePeerAccess())时,所有在对等上下文中使用cuMemAlloc()和cuMemAllocPitch()分配的内存将立即可以被当前上下文访问。在当前上下文中访问任何对等内存的设备指针值,与在对等上下文中访问该内存的指针值相同。
异常情况与不连续寻址
并非所有内存都能通过主机端访问的指针值在设备端访问。这些例外情况包括使用cuMemHostRegister()注册的主机内存,以及使用CU_MEMHOSTALLOC_WRITECOMBINED标志分配的主机内存。对于这些特殊情况,内存会存在独立的主机地址和设备地址。设备地址保证不会与任何有效的主机指针范围重叠,并且在所有支持统一寻址的上下文中保证具有相同的值。
在使用统一寻址的当前上下文时,可以通过cuMemHostGetDevicePointer()查询此设备地址。无论是主机指针还是统一设备指针值,都可以通过cuMemcpy()及类似函数使用CU_MEMORYTYPE_UNIFIED内存类型来引用此内存。
Functions
- CUresult cuMemAdvise ( CUdeviceptr devPtr, size_t count, CUmem_advise advice, CUdevice device )
- Advise about the usage of a given memory range.
- CUresult cuMemAdvise_v2 ( CUdeviceptr devPtr, size_t count, CUmem_advise advice, CUmemLocation location )
- Advise about the usage of a given memory range.
- CUresult cuMemPrefetchAsync ( CUdeviceptr devPtr, size_t count, CUdevice dstDevice, CUstream hStream )
- Prefetches memory to the specified destination device.
- CUresult cuMemPrefetchAsync_v2 ( CUdeviceptr devPtr, size_t count, CUmemLocation location, unsigned int flags, CUstream hStream )
- Prefetches memory to the specified destination location.
- CUresult cuMemRangeGetAttribute ( void* data, size_t dataSize, CUmem_range_attribute attribute, CUdeviceptr devPtr, size_t count )
- Query an attribute of a given memory range.
- CUresult cuMemRangeGetAttributes ( void** data, size_t* dataSizes, CUmem_range_attribute* attributes, size_t numAttributes, CUdeviceptr devPtr, size_t count )
- Query attributes of a given memory range.
- CUresult cuPointerGetAttribute ( void* data, CUpointer_attribute attribute, CUdeviceptr ptr )
- Returns information about a pointer.
- CUresult cuPointerGetAttributes ( unsigned int numAttributes, CUpointer_attribute* attributes, void** data, CUdeviceptr ptr )
- Returns information about a pointer.
- CUresult cuPointerSetAttribute ( const void* value, CUpointer_attribute attribute, CUdeviceptr ptr )
- Set attributes on a previously allocated memory region.
Functions
- CUresult cuMemAdvise ( CUdeviceptr devPtr, size_t count, CUmem_advise advice, CUdevice device )
-
提供关于给定内存范围使用情况的建议。
参数
- devPtr
- - Pointer to memory to set the advice for
- count
- - Size in bytes of the memory range
- advice
- - Advice to be applied for the specified memory range
- device
- - Device to apply the advice for
描述
请注意,此API有一个更新版本cuMemAdvise_v2。它将在13.0版本中取代当前版本,当前版本保留是为了保持小版本兼容性。
向统一内存子系统提供关于从devPtr开始、大小为count字节的内存区域使用模式的建议。在应用建议之前,内存区域的起始地址和结束地址将分别向下和向上取整以对齐CPU页面大小。该内存区域必须引用通过cuMemAllocManaged分配的托管内存或通过__managed__变量声明的内存。该内存区域也可以引用系统分配的可分页内存,前提是它表示一个有效的、主机可访问的内存区域,并且满足下面概述的advice所施加的所有额外约束。指定无效的系统分配可分页内存区域将导致返回错误。
advice 参数可以接受以下值:
-
CU_MEM_ADVISE_SET_READ_MOSTLY: 表示该数据将主要被读取而仅偶尔写入。任何处理器对该区域的读取访问都会在该处理器内存中创建至少被访问页面的只读副本。此外, 如果对该区域调用cuMemPrefetchAsync,则会在目标处理器上创建数据的只读副本。如果任何处理器写入该区域, 除发生写入的副本外,相应页面的所有其他副本都将失效。此建议将忽略device参数。请注意,要实现页面读取复制, 访问处理器必须是CPU或具有设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS非零值的GPU。此外,如果在未设置设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS的设备上创建上下文,则在销毁所有此类上下文之前不会发生读取复制。如果内存区域引用有效的系统分配可分页内存, 则访问设备必须具有设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS的非零值才能在该设备上创建只读副本。但需注意, 如果访问设备还具有设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS_USES_HOST_PAGE_TABLES的非零值, 则设置此建议不会在该设备访问此内存区域时创建只读副本。
-
CU_MEM_ADVISE_UNSET_READ_MOSTLY: 撤销CU_MEM_ADVISE_SET_READ_MOSTLY的效果,并阻止统一内存驱动程序尝试对内存范围进行启发式读取复制。任何读取复制的数据副本将被合并为单个副本。如果页面有首选位置且其中一个读取复制的副本驻留在该位置,则合并后的副本将位于首选位置。否则,所选位置是任意的。
-
CU_MEM_ADVISE_SET_PREFERRED_LOCATION: 该建议将数据的首选位置设置为属于device的内存。传入CU_DEVICE_CPU作为device会将首选位置设为主机内存。如果device是GPU,则该设备必须具有非零值的设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS。设置首选位置不会立即导致数据迁移到该位置,而是在该内存区域发生故障时指导迁移策略。如果数据已在首选位置且故障处理器无需迁移数据即可建立映射,则将避免数据迁移。反之,如果数据不在首选位置或无法建立直接映射,则数据将迁移到访问它的处理器。需注意,设置首选位置不会阻止使用cuMemPrefetchAsync完成的数据预取。设置首选位置可能覆盖统一内存驱动中的页面抖动检测和解决逻辑。通常,如果检测到页面在主机与设备内存间持续抖动,统一内存驱动最终可能将该页面固定到主机内存。但如果将首选位置设为设备内存,则该页面将无限期持续抖动。如果在该内存区域或其任何子集上还设置了CU_MEM_ADVISE_SET_READ_MOSTLY,则与该建议相关的策略将覆盖本建议的策略,除非如CU_MEM_ADVISE_SET_READ_MOSTLY建议描述所述,来自device的读取访问不会在该设备上创建只读副本。如果内存区域引用有效的系统分配可分页内存,则device必须具有非零值的设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS。
-
CU_MEM_ADVISE_SET_ACCESSED_BY: 此建议表示数据将被device访问。传入CU_DEVICE_CPU作为device将为CPU设置建议。如果device是GPU,则设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS必须非零。此建议不会导致数据迁移,本身也不会影响数据的位置。相反,只要数据位置允许建立映射,它就会使数据始终映射到指定处理器的页表中。如果数据因任何原因迁移,映射也会相应更新。在数据局部性不重要但需要避免缺页错误的场景中推荐使用此建议。例如考虑一个启用了点对点访问的多GPU系统,其中一个GPU上的数据偶尔会被对等GPU访问。在此类场景中,将数据迁移到其他GPU并不重要,因为访问不频繁且迁移开销可能过高。但预防缺页错误仍有助于提高性能,因此预先设置映射很有用。请注意,当CPU访问此数据时,数据可能会迁移到主机内存,因为CPU通常无法直接访问设备内存。任何为此数据设置了CU_MEM_ADVISE_SET_ACCESSED_BY标志的GPU现在都会更新其映射以指向主机内存中的页面。如果在此内存区域或其任何子集上还设置了CU_MEM_ADVISE_SET_READ_MOSTLY,则与该建议相关的策略将覆盖此建议的策略。此外,如果此内存区域或其任何子集的优选位置也是device,则与CU_MEM_ADVISE_SET_PREFERRED_LOCATION相关的策略将覆盖此建议的策略。如果内存区域引用有效的系统分配可分页内存,则device必须具有非零值的设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS。此外,如果device的设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS_USES_HOST_PAGE_TABLES具有非零值,则此调用无效。
-
CU_MEM_ADVISE_UNSET_ACCESSED_BY: 撤销CU_MEM_ADVISE_SET_ACCESSED_BY的效果。来自device的任何数据映射可能随时被移除,导致访问产生非致命页面错误。如果内存区域指向有效的系统分配可分页内存,则device必须具有设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS的非零值。此外,如果device对于设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS_USES_HOST_PAGE_TABLES具有非零值,则此调用无效。
另请参阅:
cuMemcpy, cuMemcpyPeer, cuMemcpyAsync, cuMemcpy3DPeerAsync, cuMemPrefetchAsync, cuMemAdvise_v2cudaMemAdvise
- CUresult cuMemAdvise_v2 ( CUdeviceptr devPtr, size_t count, CUmem_advise advice, CUmemLocation location )
-
提供关于给定内存范围使用情况的建议。
参数
- devPtr
- - Pointer to memory to set the advice for
- count
- - Size in bytes of the memory range
- advice
- - Advice to be applied for the specified memory range
- location
- - location to apply the advice for
描述
向统一内存子系统提供关于从devPtr开始、大小为count字节的内存范围使用模式的建议。在应用建议之前,内存范围的起始地址和结束地址将分别向下和向上取整以对齐CPU页面大小。该内存范围必须指向通过cuMemAllocManaged分配的托管内存或通过__managed__变量声明的内存。该内存范围也可以指向系统分配的可分页内存,前提是它表示一个有效的、主机可访问的内存区域,并且满足下文概述的advice施加的所有额外约束。指定无效的系统分配可分页内存范围将导致返回错误。
advice 参数可以接受以下值:
-
CU_MEM_ADVISE_SET_READ_MOSTLY: 表示该数据将主要用于读取而偶尔写入。任何处理器对该区域的读取访问都会在该处理器内存中创建至少被访问页面的只读副本。此外, 如果对该区域调用cuMemPrefetchAsync或cuMemPrefetchAsync_v2,将在目标处理器上创建数据的只读副本。若cuMemPrefetchAsync_v2的目标位置是主机NUMA节点且另一个主机NUMA节点上已存在只读副本,则该副本将被迁移至目标主机NUMA节点。任何处理器对该区域的写入操作都会使相应页面的所有副本失效(写入发生的副本除外)。 若写入处理器是CPU且页面的首选位置是主机NUMA节点,则该页面也将被迁移至该主机NUMA节点。此建议将忽略location参数。请注意,要实现页面读取复制,访问处理器必须是CPU或具有设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS非零值的GPU。此外,如果在未设置设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS的设备上创建上下文,则在这些上下文全部销毁前不会发生读取复制。若内存区域指向有效的系统分配可分页内存,则访问设备必须具有设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS非零值才能在该设备上创建只读副本。但需注意,若访问设备同时具有设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS_USES_HOST_PAGE_TABLES非零值,则设置此建议不会在该设备访问此内存区域时创建只读副本。
-
CU_MEM_ADVISE_UNSET_READ_MOSTLY: 撤销CU_MEM_ADVISE_SET_READ_MOSTLY的效果,并阻止统一内存驱动程序尝试对内存范围进行启发式读取复制。任何读取复制的数据副本将被合并为单个副本。如果页面有首选位置且其中一个读取复制的副本驻留在该位置,则合并后的副本将位于首选位置。否则,所选位置是任意的。注意:此建议忽略location参数。
-
CU_MEM_ADVISE_SET_PREFERRED_LOCATION: This advice sets the preferred location for the data to be the memory belonging to location. When CUmemLocation::type is CU_MEM_LOCATION_TYPE_HOST, CUmemLocation::id is ignored and the preferred location is set to be host memory. To set the preferred location to a specific host NUMA node, applications must set CUmemLocation::type to CU_MEM_LOCATION_TYPE_HOST_NUMA and CUmemLocation::id must specify the NUMA ID of the host NUMA node. If CUmemLocation::type is set to CU_MEM_LOCATION_TYPE_HOST_NUMA_CURRENT, CUmemLocation::id will be ignored and the the host NUMA node closest to the calling thread's CPU will be used as the preferred location. If CUmemLocation::type is a CU_MEM_LOCATION_TYPE_DEVICE, then CUmemLocation::id must be a valid device ordinal and the device must have a non-zero value for the device attribute CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS. Setting the preferred location does not cause data to migrate to that location immediately. Instead, it guides the migration policy when a fault occurs on that memory region. If the data is already in its preferred location and the faulting processor can establish a mapping without requiring the data to be migrated, then data migration will be avoided. On the other hand, if the data is not in its preferred location or if a direct mapping cannot be established, then it will be migrated to the processor accessing it. It is important to note that setting the preferred location does not prevent data prefetching done using cuMemPrefetchAsync. Having a preferred location can override the page thrash detection and resolution logic in the Unified Memory driver. Normally, if a page is detected to be constantly thrashing between for example host and device memory, the page may eventually be pinned to host memory by the Unified Memory driver. But if the preferred location is set as device memory, then the page will continue to thrash indefinitely. If CU_MEM_ADVISE_SET_READ_MOSTLY is also set on this memory region or any subset of it, then the policies associated with that advice will override the policies of this advice, unless read accesses from location will not result in a read-only copy being created on that procesor as outlined in description for the advice CU_MEM_ADVISE_SET_READ_MOSTLY. If the memory region refers to valid system-allocated pageable memory, and CUmemLocation::type is CU_MEM_LOCATION_TYPE_DEVICE then CUmemLocation::id must be a valid device that has a non-zero alue for the device attribute CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS.
-
CU_MEM_ADVISE_UNSET_PREFERRED_LOCATION: 撤销CU_MEM_ADVISE_SET_PREFERRED_LOCATION的效果并将首选位置设置为无。对于此建议,location参数将被忽略。
-
CU_MEM_ADVISE_SET_ACCESSED_BY: This advice implies that the data will be accessed by processor location. The CUmemLocation::type must be either CU_MEM_LOCATION_TYPE_DEVICE with CUmemLocation::id representing a valid device ordinal or CU_MEM_LOCATION_TYPE_HOST and CUmemLocation::id will be ignored. All other location types are invalid. If CUmemLocation::id is a GPU, then the device attribute CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS must be non-zero. This advice does not cause data migration and has no impact on the location of the data per se. Instead, it causes the data to always be mapped in the specified processor's page tables, as long as the location of the data permits a mapping to be established. If the data gets migrated for any reason, the mappings are updated accordingly. This advice is recommended in scenarios where data locality is not important, but avoiding faults is. Consider for example a system containing multiple GPUs with peer-to-peer access enabled, where the data located on one GPU is occasionally accessed by peer GPUs. In such scenarios, migrating data over to the other GPUs is not as important because the accesses are infrequent and the overhead of migration may be too high. But preventing faults can still help improve performance, and so having a mapping set up in advance is useful. Note that on CPU access of this data, the data may be migrated to host memory because the CPU typically cannot access device memory directly. Any GPU that had the CU_MEM_ADVISE_SET_ACCESSED_BY flag set for this data will now have its mapping updated to point to the page in host memory. If CU_MEM_ADVISE_SET_READ_MOSTLY is also set on this memory region or any subset of it, then the policies associated with that advice will override the policies of this advice. Additionally, if the preferred location of this memory region or any subset of it is also location, then the policies associated with CU_MEM_ADVISE_SET_PREFERRED_LOCATION will override the policies of this advice. If the memory region refers to valid system-allocated pageable memory, and CUmemLocation::type is CU_MEM_LOCATION_TYPE_DEVICE then device in CUmemLocation::id must have a non-zero value for the device attribute CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS. Additionally, if CUmemLocation::id has a non-zero value for the device attribute CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS_USES_HOST_PAGE_TABLES, then this call has no effect.
-
CU_MEM_ADVISE_UNSET_ACCESSED_BY: 撤销CU_MEM_ADVISE_SET_ACCESSED_BY的效果。来自location的任何数据映射可能随时被移除,导致访问产生非致命页面错误。如果内存区域引用有效的系统分配可分页内存,且CUmemLocation::type为CU_MEM_LOCATION_TYPE_DEVICE,则CUmemLocation::id中的设备必须具有非零值的设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS。此外,如果CUmemLocation::id对于设备属性CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS_USES_HOST_PAGE_TABLES具有非零值,则此调用无效。
另请参阅:
cuMemcpy, cuMemcpyPeer, cuMemcpyAsync, cuMemcpy3DPeerAsync, cuMemPrefetchAsync, cuMemAdvisecudaMemAdvise
- CUresult cuMemPrefetchAsync ( CUdeviceptr devPtr, size_t count, CUdevice dstDevice, CUstream hStream )
-
将内存预取到指定的目标设备。
参数
- devPtr
- - Pointer to be prefetched
- count
- - Size in bytes
- dstDevice
- - Destination device to prefetch to
- hStream
- - Stream to enqueue prefetch operation
描述
请注意,此API有一个更新版本cuMemPrefetchAsync_v2。它将在13.0版本中取代当前版本,当前版本保留是为了保持小版本兼容性。
将内存预取到指定的目标设备。devPtr是要预取内存的基设备指针,dstDevice是目标设备。count指定要复制的字节数。hStream是操作入队的流。内存范围必须引用通过cuMemAllocManaged分配的托管内存或通过__managed__变量声明的内存,在具有非零CU_DEVICE_ATTRIBUTE_PAGEABLE_MEMORY_ACCESS的系统上,它也可以引用系统分配的内存。
为dstDevice传入CU_DEVICE_CPU会将数据预取到主机内存。如果dstDevice是GPU,则设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS必须非零。此外,hStream必须与具有非零值设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS的设备相关联。
在将预取操作加入流之前,内存范围的起始地址和结束地址将分别向下舍入和向上舍入,以与CPU页面大小对齐。
如果该内存区域尚未分配物理内存,则该内存区域将在目标设备上被填充并映射。如果没有足够的内存预取所需区域,统一内存驱动程序可能会将其他cuMemAllocManaged分配的内存页驱逐到主机内存中以腾出空间。使用cuMemAlloc或cuArrayCreate分配的设备内存不会被驱逐。
默认情况下,迁移页面的原有位置映射会被移除,而新位置的映射仅会在dstDevice设备上建立。但具体行为还取决于通过cuMemAdvise对此内存范围应用的设置,如下所述:
如果在此内存范围的任何子集上设置了CU_MEM_ADVISE_SET_READ_MOSTLY,则该子集将在dstDevice上创建页面的只读副本。
如果对此内存范围的任何子集调用了CU_MEM_ADVISE_SET_PREFERRED_LOCATION,那么即使dstDevice不是该内存范围内任何页面的首选位置,这些页面也将被迁移到dstDevice。
如果在此内存范围的任何子集上调用了CU_MEM_ADVISE_SET_ACCESSED_BY,那么来自所有适当处理器的对这些页面的映射将被更新以引用新位置(如果能够建立此类映射)。否则,这些映射将被清除。
请注意,此API并非功能必需,仅用于通过允许应用程序在数据被访问前将其迁移至合适位置来提升性能。对该内存范围的访问始终是连贯的,即使数据正在主动迁移过程中也允许访问。
请注意,此函数相对于主机和其他设备上的所有工作是异步的。
另请参阅:
cuMemcpy, cuMemcpyPeer, cuMemcpyAsync, cuMemcpy3DPeerAsync, cuMemAdvise, cuMemPrefetchAsynccudaMemPrefetchAsync_v2
- CUresult cuMemPrefetchAsync_v2 ( CUdeviceptr devPtr, size_t count, CUmemLocation location, unsigned int flags, CUstream hStream )
-
将内存预取到指定的目标位置。
参数
- devPtr
- - Pointer to be prefetched
- count
- - Size in bytes
- location
- flags
- - flags for future use, must be zero now.
- hStream
- - Stream to enqueue prefetch operation
描述
将内存预取到指定的目标位置。devPtr是要预取内存的基础设备指针,location指定目标位置。count指定要复制的字节数。hStream是操作入队的流。内存范围必须引用通过cuMemAllocManaged分配的托管内存或通过__managed__变量声明的内存。
为CUmemLocation::type指定CU_MEM_LOCATION_TYPE_DEVICE会将内存预取到由设备序号CUmemLocation::id指定的GPU上,该设备必须具有非零值的设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS。此外,hStream必须与具有非零值设备属性CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS的设备相关联。为CUmemLocation::type指定CU_MEM_LOCATION_TYPE_HOST会将数据预取到主机内存。应用程序可以通过为CUmemLocation::type指定CU_MEM_LOCATION_TYPE_HOST_NUMA并在CUmemLocation::id中指定有效的主机NUMA节点ID,请求将内存预取到特定的主机NUMA节点。用户还可以通过为CUmemLocation::type指定CU_MEM_LOCATION_TYPE_HOST_NUMA_CURRENT,请求将内存预取到最接近当前线程CPU的主机NUMA节点。请注意,当CUmemLocation::type是CU_MEM_LOCATION_TYPE_HOST或CU_MEM_LOCATION_TYPE_HOST_NUMA_CURRENT时,CUmemLocation::id将被忽略。
在将预取操作加入流之前,内存范围的起始地址和结束地址将分别向下舍入和向上舍入,以与CPU页面大小对齐。
如果该内存区域尚未分配物理内存,则该内存区域将在目标设备上被填充并映射。如果没有足够的内存预取所需区域,统一内存驱动程序可能会将其他cuMemAllocManaged分配的内存页驱逐到主机内存中以腾出空间。使用cuMemAlloc或cuArrayCreate分配的设备内存不会被驱逐。
默认情况下,迁移页面前一位置的所有映射都会被移除,且新位置的映射仅会在目标位置建立。但具体行为还取决于通过cuMemAdvise对此内存范围应用的设置,如下所述:
如果在此内存范围的任何子集上设置了CU_MEM_ADVISE_SET_READ_MOSTLY,则该子集将在目标位置创建页面的只读副本。 但如果目标位置是主机NUMA节点,则该子集中已位于其他主机NUMA节点的任何页面都将被传输到目标位置。
如果对此内存范围的任何子集调用了CU_MEM_ADVISE_SET_PREFERRED_LOCATION,那么即使location不是该内存范围内任何页面的首选位置,这些页面也将被迁移到location。
如果在此内存范围的任何子集上调用了CU_MEM_ADVISE_SET_ACCESSED_BY,那么来自所有相应处理器的对这些页面的映射将被更新以引用新位置(如果能够建立此类映射)。否则,这些映射将被清除。
请注意,此API并非功能必需,仅用于通过允许应用程序在数据被访问前将其迁移至合适位置来提升性能。对该内存范围的访问始终是连贯的,即使数据正在主动迁移过程中也允许访问。
请注意,此函数相对于主机和其他设备上的所有工作是异步的。
另请参阅:
cuMemcpy, cuMemcpyPeer, cuMemcpyAsync, cuMemcpy3DPeerAsync, cuMemAdvise, cuMemPrefetchAsynccudaMemPrefetchAsync_v2
- CUresult cuMemRangeGetAttribute ( void* data, size_t dataSize, CUmem_range_attribute attribute, CUdeviceptr devPtr, size_t count )
-
查询给定内存范围的属性。
参数
- data
- - A pointers to a memory location where the result of each attribute query will be written to.
- dataSize
- - Array containing the size of data
- attribute
- - The attribute to query
- devPtr
- - Start of the range to query
- count
- - Size of the range to query
描述
查询从devPtr开始、大小为count字节的内存范围的属性。该内存范围必须指向通过cuMemAllocManaged分配的托管内存或通过__managed__变量声明的内存。
attribute 参数可以接受以下值:
-
CU_MEM_RANGE_ATTRIBUTE_READ_MOSTLY: 如果指定此属性,data将被解释为32位整数,且dataSize必须为4。如果给定内存范围内的所有页面都启用了读取复制功能,则返回结果为1,否则返回0。
-
CU_MEM_RANGE_ATTRIBUTE_PREFERRED_LOCATION: 如果指定此属性,data将被解释为32位整数,且dataSize必须为4。返回的结果将是GPU设备ID(如果内存范围内所有页面的首选位置都是该GPU),或是CU_DEVICE_CPU(如果所有页面的首选位置都是CPU),或是CU_DEVICE_INVALID(如果页面不具有相同的首选位置或某些页面根本没有首选位置)。请注意,查询时内存范围内页面的实际位置可能与首选位置不同。
-
CU_MEM_RANGE_ATTRIBUTE_ACCESSED_BY: 如果指定此属性,data将被解释为一个32位整数数组,且dataSize必须是4的非零倍数。返回的结果将是一个设备ID列表,这些设备对该整个内存范围设置了CU_MEM_ADVISE_SET_ACCESSED_BY。如果任何设备未对该整个内存范围设置此建议,则该设备将不会被包含。如果data大于对该内存范围设置此建议的设备数量,则所有额外空间将返回CU_DEVICE_INVALID。例如,如果dataSize为12(即data有3个元素)且只有设备0设置了建议,则返回的结果将是{ 0, CU_DEVICE_INVALID, CU_DEVICE_INVALID }。如果data小于设置此建议的设备数量,则只返回能放入数组的设备数量。但无法保证返回哪些特定设备。
-
CU_MEM_RANGE_ATTRIBUTE_LAST_PREFETCH_LOCATION: 如果指定此属性,data将被解释为32位整数,且dataSize必须为4。返回的结果将是内存范围内所有页面通过cuMemPrefetchAsync显式预取的最后一个位置。根据最后一次预取目标是GPU还是CPU,该位置将返回GPU ID或CU_DEVICE_CPU。 如果内存范围内有任何页面从未显式预取过,或者所有页面未被预取到同一位置, 则将返回CU_DEVICE_INVALID。请注意,这仅返回应用程序请求预取内存范围的最后一个目标位置。 它并不指示预取操作是否已完成或甚至已开始。
-
CU_MEM_RANGE_ATTRIBUTE_PREFERRED_LOCATION_TYPE: If this attribute is specified, data will be interpreted as a CUmemLocationType, and dataSize must be sizeof(CUmemLocationType). The CUmemLocationType returned will be CU_MEM_LOCATION_TYPE_DEVICE if all pages in the memory range have the same GPU as their preferred location, or CUmemLocationType will be CU_MEM_LOCATION_TYPE_HOST if all pages in the memory range have the CPU as their preferred location, or it will be CU_MEM_LOCATION_TYPE_HOST_NUMA if all the pages in the memory range have the same host NUMA node ID as their preferred location or it will be CU_MEM_LOCATION_TYPE_INVALID if either all the pages don't have the same preferred location or some of the pages don't have a preferred location at all. Note that the actual location type of the pages in the memory range at the time of the query may be different from the preferred location type.
-
CU_MEM_RANGE_ATTRIBUTE_PREFERRED_LOCATION_ID: 如果指定此属性,data将被解释为32位整数,且dataSize必须为4。如果对相同地址范围的CU_MEM_RANGE_ATTRIBUTE_PREFERRED_LOCATION_TYPE查询返回CU_MEM_LOCATION_TYPE_DEVICE,则它将是一个有效的设备序号;如果返回CU_MEM_LOCATION_TYPE_HOST_NUMA,则它将是一个有效的主机NUMA节点ID;如果返回任何其他位置类型,则应忽略该ID。
-
-
CU_MEM_RANGE_ATTRIBUTE_LAST_PREFETCH_LOCATION_TYPE: If this attribute is specified, data will be interpreted as a CUmemLocationType, and dataSize must be sizeof(CUmemLocationType). The result returned will be the last location to which all pages in the memory range were prefetched explicitly via cuMemPrefetchAsync. The CUmemLocationType returned will be CU_MEM_LOCATION_TYPE_DEVICE if the last prefetch location was a GPU or CU_MEM_LOCATION_TYPE_HOST if it was the CPU or CU_MEM_LOCATION_TYPE_HOST_NUMA if the last prefetch location was a specific host NUMA node. If any page in the memory range was never explicitly prefetched or if all pages were not prefetched to the same location, CUmemLocationType will be CU_MEM_LOCATION_TYPE_INVALID. Note that this simply returns the last location type that the application requested to prefetch the memory range to. It gives no indication as to whether the prefetch operation to that location has completed or even begun.
-
CU_MEM_RANGE_ATTRIBUTE_LAST_PREFETCH_LOCATION_ID: 如果指定此属性,data将被解释为32位整数,且dataSize必须为4。如果对相同地址范围的CU_MEM_RANGE_ATTRIBUTE_LAST_PREFETCH_LOCATION_TYPE查询返回CU_MEM_LOCATION_TYPE_DEVICE,则它将是一个有效的设备序号;如果返回CU_MEM_LOCATION_TYPE_HOST_NUMA,则它将是一个有效的主机NUMA节点ID;如果返回任何其他位置类型,则应忽略该ID。
-
另请参阅:
cuMemRangeGetAttributes, cuMemPrefetchAsync, cuMemAdvise, cudaMemRangeGetAttribute
- CUresult cuMemRangeGetAttributes ( void** data, size_t* dataSizes, CUmem_range_attribute* attributes, size_t numAttributes, CUdeviceptr devPtr, size_t count )
-
查询给定内存范围的属性。
参数
- data
- - A two-dimensional array containing pointers to memory locations where the result of each attribute query will be written to.
- dataSizes
- - Array containing the sizes of each result
- attributes
- - An array of attributes to query (numAttributes and the number of attributes in this array should match)
- numAttributes
- - Number of attributes to query
- devPtr
- - Start of the range to query
- count
- - Size of the range to query
返回
CUDA_SUCCESS, CUDA_ERROR_DEINITIALIZED, CUDA_ERROR_INVALID_CONTEXT, CUDA_ERROR_INVALID_VALUE, CUDA_ERROR_INVALID_DEVICE
描述
查询从devPtr开始、大小为count字节的内存范围的属性。该内存范围必须指向通过cuMemAllocManaged分配的托管内存或通过__managed__变量声明的内存。attributes数组将被解释为包含numAttributes个条目。dataSizes数组同样会被解释为包含numAttributes个条目。查询结果将存储在data中。
支持的属性列表如下。有关属性描述和限制,请参阅cuMemRangeGetAttribute。
Note:请注意,此函数也可能返回之前异步启动的错误代码。
另请参阅:
cuMemRangeGetAttribute, cuMemAdvise, cuMemPrefetchAsync, cudaMemRangeGetAttributes
- CUresult cuPointerGetAttribute ( void* data, CUpointer_attribute attribute, CUdeviceptr ptr )
-
返回关于指针的信息。
参数
- data
- - Returned pointer attribute value
- attribute
- - Pointer attribute to query
- ptr
- - Pointer
返回
CUDA_SUCCESS, CUDA_ERROR_DEINITIALIZED, CUDA_ERROR_NOT_INITIALIZED, CUDA_ERROR_INVALID_CONTEXT, CUDA_ERROR_INVALID_VALUE, CUDA_ERROR_INVALID_DEVICE
描述
支持的属性包括:
返回在*data中分配或注册ptr的CUcontext。data的类型必须是CUcontext *。
如果ptr不是由使用统一虚拟寻址的CUcontext分配、映射或注册的,则返回CUDA_ERROR_INVALID_VALUE。
在*data中返回ptr所指向内存的物理内存类型,作为CUmemorytype枚举值。data的类型必须是无符号整型。
如果ptr指向设备内存,那么*data将被设置为CU_MEMORYTYPE_DEVICE。该内存所在的特定CUdevice就是通过ptr的CU_POINTER_ATTRIBUTE_CONTEXT属性返回的CUcontext所对应的CUdevice。
如果ptr指向主机内存,则*data将被设置为CU_MEMORYTYPE_HOST。
如果ptr不是由使用统一虚拟寻址的CUcontext分配、映射或注册的,则返回CUDA_ERROR_INVALID_VALUE。
如果当前的CUcontext不支持统一虚拟寻址,则返回CUDA_ERROR_INVALID_CONTEXT。
返回*data中的设备指针值,通过该值当前CUcontext中运行的内核可以访问ptr。data的类型必须为CUdeviceptr *。
如果不存在设备指针值,使得当前CUcontext中运行的内核可以通过该指针访问ptr,则将返回CUDA_ERROR_INVALID_VALUE。
如果没有当前的CUcontext,则返回CUDA_ERROR_INVALID_CONTEXT。
除了下面讨论的特殊非连续寻址情况外,*data中返回的值将等于输入值ptr。
在*data中返回主机程序可通过其访问ptr的主机指针值。data的类型必须为void **。如果不存在主机程序可直接访问ptr的主机指针值,则返回CUDA_ERROR_INVALID_VALUE。
除了下面讨论的特殊非连续寻址情况外,*data中返回的值将等于输入值ptr。
返回*data中的两个令牌,用于nv-p2p.h Linux内核接口。data必须是CUDA_POINTER_ATTRIBUTE_P2P_TOKENS类型的结构体。
ptr 必须指向通过 cuMemAlloc() 分配的内存。请注意 p2pToken 和 vaSpaceToken 仅在源分配的生命周期内有效。后续在同一地址的分配可能会返回完全不同的令牌。查询此属性会产生副作用,会为 ptr 指向的内存区域设置 CU_POINTER_ATTRIBUTE_SYNC_MEMOPS 属性。
一个布尔属性,当设置时,确保在ptr指向的内存区域上发起的同步内存操作将始终保持同步。有关同步内存操作可能表现出异步行为的情况的更多信息,请参阅标题为"API同步行为"的部分中的进一步文档。
在*data中返回一个缓冲区ID,该ID保证在进程内是唯一的。data必须指向一个无符号长整型(unsigned long long)。
ptr 必须是指向通过CUDA内存分配API获取的内存的指针。从任何CUDA内存分配API进行的每次内存分配,在进程生命周期内都会拥有唯一的ID。后续的分配不会重复使用之前已释放分配的ID。这些ID仅在单个进程内保持唯一性。
返回*data中的一个布尔值,用于指示指针是否指向托管内存。
如果ptr不是有效的CUDA指针,则返回CUDA_ERROR_INVALID_VALUE。
在*data中返回一个整数,表示分配或注册内存时所针对设备的设备序号。
返回*data中的一个布尔值,用于指示该指针是否映射到适合cudaIpcGetMemHandle的分配。
在*data中返回设备指针ptr所引用的分配起始地址。请注意,这不一定是映射区域的地址,而是ptr引用的可映射地址范围的起始地址(例如来自cuMemAddressReserve的分配)。
返回*data中由设备指针ptr引用的分配大小。请注意,这不一定是映射区域的大小,而是ptr引用的可映射地址范围的大小(例如来自cuMemAddressReserve)。要获取映射区域的大小,请参阅cuMemGetAddressRange
返回*data中的一个布尔值,用于指示该指针是否位于已映射到后备分配的有效地址范围内。
返回一个位掩码,表示可以传递给cuMemExportToShareableHandle的内存分配所允许的句柄类型。
在*data中返回分配内存所在的内存池句柄。
返回*data中的一个布尔值,用于指示该指针是否指向可用于硬件加速解压缩的内存。
请注意,在统一虚拟地址空间中,大多数分配的主机端和设备端访问指针是相同的。例外情况包括:
-
使用cuMemHostRegister注册的用户内存
-
使用cuMemHostAlloc函数并带有CU_MEMHOSTALLOC_WRITECOMBINED标志分配的主机内存 对于这类分配,将存在独立且互斥的主机和设备地址来访问该内存区域。具体而言
-
主机地址将对应一个无效的未映射设备地址(如果从设备访问将导致异常)
-
设备地址将对应一个无效的未映射主机地址(如果从主机访问会导致异常)。对于这类分配,可以通过查询CU_POINTER_ATTRIBUTE_HOST_POINTER和CU_POINTER_ATTRIBUTE_DEVICE_POINTER来从任一地址检索主机和设备地址。
Note:请注意,此函数也可能返回之前异步启动的错误代码。
另请参阅:
cuPointerSetAttribute, cuMemAlloc, cuMemFree, cuMemAllocHost, cuMemFreeHost, cuMemHostAlloc, cuMemHostRegister, cuMemHostUnregister, cudaPointerGetAttributes
- CUresult cuPointerGetAttributes ( unsigned int numAttributes, CUpointer_attribute* attributes, void** data, CUdeviceptr ptr )
-
返回关于指针的信息。
参数
- numAttributes
- - Number of attributes to query
- attributes
- - An array of attributes to query (numAttributes and the number of attributes in this array should match)
- data
- - A two-dimensional array containing pointers to memory locations where the result of each attribute query will be written to.
- ptr
- - Pointer to query
返回
CUDA_SUCCESS, CUDA_ERROR_DEINITIALIZED, CUDA_ERROR_INVALID_CONTEXT, CUDA_ERROR_INVALID_VALUE, CUDA_ERROR_INVALID_DEVICE
描述
支持的属性包括(有关属性描述和限制,请参阅cuPointerGetAttribute):
与cuPointerGetAttribute不同,当遇到的ptr不是有效的CUDA指针时,此函数不会返回错误。相反,属性会被赋予默认的NULL值并返回CUDA_SUCCESS。
如果ptr不是由使用UVA(统一虚拟寻址)的CUcontext分配、映射或注册的,则返回CUDA_ERROR_INVALID_CONTEXT。
Note:请注意,此函数也可能返回之前异步启动的错误代码。
另请参阅:
cuPointerGetAttribute, cuPointerSetAttribute, cudaPointerGetAttributes
- CUresult cuPointerSetAttribute ( const void* value, CUpointer_attribute attribute, CUdeviceptr ptr )
-
在先前分配的内存区域上设置属性。
参数
- value
- - Pointer to memory containing the value to be set
- attribute
- - Pointer attribute to set
- ptr
- - Pointer to a memory region allocated using CUDA memory allocation APIs
返回
CUDA_SUCCESS, CUDA_ERROR_DEINITIALIZED, CUDA_ERROR_NOT_INITIALIZED, CUDA_ERROR_INVALID_CONTEXT, CUDA_ERROR_INVALID_VALUE, CUDA_ERROR_INVALID_DEVICE
描述
支持的属性包括:
一个布尔属性,可以设置为1或取消设置为0。当设置时,ptr指向的内存区域保证始终同步执行内存操作。如果在设置此属性时存在先前已启动但尚未完成的同步内存操作,则该函数将等待这些内存操作完成后才返回。更多关于同步内存操作可能表现出异步行为的情况,请参阅标题为"API同步行为"章节中的进一步文档说明。value将被视为指向要设置此属性的无符号整数的指针。
Note:请注意,此函数也可能返回之前异步启动的错误代码。
另请参阅:
cuPointerGetAttribute, cuPointerGetAttributes, cuMemAlloc, cuMemFree, cuMemAllocHost, cuMemFreeHost, cuMemHostAlloc, cuMemHostRegister, cuMemHostUnregister