6.14. 统一寻址

本节介绍CUDA运行时应用程序编程接口的统一寻址功能。

概述

CUDA设备可以与主机共享统一地址空间。对于这些设备来说,设备指针和主机指针没有区别——相同的指针值既可用于主机程序访问内存,也可用于设备上运行的内核访问内存(以下列举的例外情况除外)。

支持的平台

可以通过调用cudaGetDeviceProperties()并检查设备属性cudaDeviceProp::unifiedAddressing来查询设备是否支持统一寻址功能。

在64位进程中会自动启用统一寻址。

从指针值查找信息

可以查询支持指针值的内存相关信息。例如,可能需要了解指针指向的是主机内存还是设备内存。另一个例子是,对于设备内存,可能需要知道该内存位于哪个CUDA设备上。这些属性可以通过函数cudaPointerGetAttributes()进行查询。

由于指针是唯一的,因此无需为指向cudaMemcpy()和其他复制函数的指针指定额外信息。复制方向参数cudaMemcpyDefault可用于指示CUDA运行时应当根据指针值自动推断其位置。

主机分配内存的自动映射

通过所有设备使用cudaMallocHost()cudaHostAlloc()分配的所有主机内存,始终可以从支持统一寻址的所有设备直接访问。无论是否指定了标志cudaHostAllocPortablecudaHostAllocMapped,情况都是如此。

通过支持统一寻址的所有设备上的内核访问已分配主机内存的指针值,与主机上访问该内存的指针值相同。对于这些分配,无需调用cudaHostGetDevicePointer()来获取设备指针。

请注意,对于使用标志cudaHostAllocWriteCombined分配的内存情况并非如此,如下文所述。

直接访问对等内存

当启用支持统一寻址的设备直接访问另一个同样支持统一寻址的对等设备时, 通过调用cudaDeviceEnablePeerAccess()函数,所有使用cudaMalloc()cudaMallocPitch()在对等设备上分配的内存将立即可以被当前设备访问。在当前设备中访问任何对等设备内存的设备指针值, 与从对等设备访问该内存时使用的指针值相同。

异常情况与不连续寻址

并非所有内存都能通过主机访问时的相同指针值在设备上访问。这些例外情况包括使用cudaHostRegister()注册的主机内存,以及使用cudaHostAllocWriteCombined标志分配的主机内存。对于这些例外情况,内存会存在独立的主机地址和设备地址。设备地址保证不会与任何有效主机指针范围重叠,并保证在所有支持统一寻址的设备上具有相同的值。

当使用统一寻址的设备处于当前状态时,可以通过cudaHostGetDevicePointer()查询此设备地址。在cudaMemcpy()及类似函数中使用cudaMemcpyDefault内存方向时,可以使用主机指针或统一设备指针值来引用此内存。

Functions

__host__cudaError_t cudaPointerGetAttributes ( cudaPointerAttributes* attributes, const void* ptr )
Returns attributes about a specified pointer.

Functions

__host__cudaError_t cudaPointerGetAttributes ( cudaPointerAttributes* attributes, const void* ptr )
返回指定指针的相关属性。
参数
attributes
- Attributes for the specified pointer
ptr
- Pointer to get attributes for
描述

*attributes中返回指针ptr的属性。如果指针不是在支持统一寻址的上下文中分配、映射或注册的,则返回cudaErrorInvalidValue

Note:

在CUDA 11.0中,传递主机指针将在cudaPointerAttributes::type中返回cudaMemoryTypeUnregistered,并且调用将返回cudaSuccess

cudaPointerAttributes 结构体定义如下:

‎    struct cudaPointerAttributes {
              enum cudaMemoryType 
                  type;
              int device;
              void *devicePointer;
              void *hostPointer;
          }
In this structure, the individual fields mean

  • device 是分配 ptr 时所对应的设备。如果 ptr 的内存类型为 cudaMemoryTypeDevice,则此参数标识 ptr 所引用的内存实际所在的设备。如果 ptr 的内存类型为 cudaMemoryTypeHost,则此参数标识分配内存时当前所处的设备(如果该设备被反初始化,那么此分配将随该设备的状态一起消失)。

  • devicePointer 是设备指针别名,当前设备可通过该别名访问由 ptr 指向的内存。如果当前设备无法直接访问 ptr 指向的内存,则该值为 NULL。

  • hostPointer 是主机指针别名,通过它可以在主机上访问由ptr引用的内存。如果主机无法直接访问ptr引用的内存,则该值为NULL。

Note:

另请参阅:

cudaGetDeviceCount, cudaGetDevice, cudaSetDevice, cudaChooseDevice, cudaInitDevice, cuPointerGetAttributes