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 内存方向来引用此内存。

函数

__host__cudaError_t cudaPointerGetAttributes ( cudaPointerAttributes* attributes, const void* ptr )
返回有关指定指针的属性。

函数

__host__cudaError_t cudaPointerGetAttributes ( cudaPointerAttributes* attributes, const void* ptr )
返回有关指定指针的属性。
参数
attributes
- 指定指针的属性
ptr
- 要获取属性的指针
描述

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

注意

在 CUDA 11.0 及更高版本中,传递主机指针将会在 cudaPointerAttributes::type 中返回 cudaMemoryTypeUnregistered,并且调用将返回 cudaSuccess

cudaPointerAttributes 结构定义如下

‎    struct cudaPointerAttributes {
              enum cudaMemoryType 
                  type;
              int device;
              void *devicePointer;
              void *hostPointer;
          }
在此结构中,各个字段的含义如下

  • device 是分配ptr所针对的设备。如果ptr的内存类型为 cudaMemoryTypeDevice,则这标识了由ptr引用的内存实际驻留的设备。如果ptr的内存类型为 cudaMemoryTypeHost,则这标识了在进行分配时为当前的设备(如果该设备被取消初始化,则此分配将随该设备的状态一起消失)。

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

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

注意

另请参阅

cudaGetDeviceCount, cudaGetDevice, cudaSetDevice, cudaChooseDevice, cudaInitDevice, cuPointerGetAttributes