6.34. 与 CUDA 驱动程序 API 的交互
本节介绍 CUDA 驱动程序 API 和 CUDA 运行时 API 之间的交互
主上下文
在一个进程中,CUDA 运行时 API 中的 CUDA 设备与 CUDA 驱动程序 API 中的 CUcontext 之间存在一对一的关系。CUDA 运行时 API 用于设备的特定上下文称为设备的主上下文。从 CUDA 运行时 API 的角度来看,设备及其主上下文是同义的。
初始化和拆卸
CUDA 运行时 API 调用在 CUDA 驱动程序 API CUcontext 上运行,该上下文是调用主机线程的当前上下文。
函数 cudaInitDevice() 确保为请求的设备初始化主上下文,但不会使其成为调用线程的当前上下文。
函数 cudaSetDevice() 初始化指定设备的主上下文,并通过调用 cuCtxSetCurrent() 使其成为调用线程的当前上下文。
CUDA 运行时 API 将在第一个需要活动上下文的 CUDA 运行时 API 调用时自动初始化设备的主上下文。如果在进行需要活动上下文的 CUDA 运行时 API 调用时,调用线程没有当前的 CUcontext,则将选择设备的主上下文,使其成为调用线程的当前上下文并进行初始化。
CUDA 运行时 API 初始化的上下文将使用 CUDA 运行时 API 函数 cudaSetDeviceFlags()、cudaD3D9SetDirect3DDevice()、cudaD3D10SetDirect3DDevice()、cudaD3D11SetDirect3DDevice()、cudaGLSetGLDevice() 和 cudaVDPAUSetVDPAUDevice() 指定的参数进行初始化。请注意,如果调用这些函数时,指定设备的主上下文已初始化,则这些函数将失败并返回 cudaErrorSetOnActiveProcess 错误,除了 cudaSetDeviceFlags(),它只会覆盖之前的设置。
主上下文将保持活动状态,直到使用 cudaDeviceReset() 显式取消初始化。函数 cudaDeviceReset() 将立即取消初始化调用线程的当前设备的主上下文。上下文将保持为所有线程的当前上下文。任何线程上的下一个需要活动上下文的 CUDA 运行时 API 调用将触发该设备主上下文的重新初始化。
请注意,主上下文是共享资源。建议除非在退出前或从未指定的启动失败中恢复,否则不要重置主上下文。
上下文互操作性
请注意,在单个进程中为每个设备使用多个 CUcontext 将显著降低性能,因此强烈建议不要这样做。相反,强烈建议使用 CUDA 运行时 API 提供的进程的隐式一对一设备到上下文映射。
如果 CUDA 驱动程序 API 创建的非主 CUcontext 是线程的当前上下文,则该线程的 CUDA 运行时 API 调用将在该 CUcontext 上运行,但以下部分列出了一些例外情况。数据类型之间的互操作性将在以下部分中讨论。
函数 cudaPointerGetAttributes() 将返回错误 cudaErrorIncompatibleDriverContext,如果正在查询的指针是由非主上下文分配的。当非主 CUcontext 为当前上下文时,可能不会调用函数 cudaDeviceEnablePeerAccess() 和其余的对等访问 API。 要将指针查询和对等访问 API 与使用 CUDA 驱动程序 API 创建的上下文一起使用,必须使用 CUDA 驱动程序 API 来访问这些功能。
所有 CUDA 运行时 API 状态(例如,全局变量的地址和值)都与其底层 CUcontext 一起传递。 特别是,如果 CUcontext 从一个线程移动到另一个线程,则所有 CUDA 运行时 API 状态也将移动到该线程。
请注意,无法附加到旧版上下文(通过 cuCtxGetApiVersion() 返回的版本为 3010 的上下文)。 在这种情况下,CUDA 运行时将返回 cudaErrorIncompatibleDriverContext 错误。
CUstream 和 cudaStream_t 之间的交互
类型 CUstream 和 cudaStream_t 是相同的,可以互换使用。
CUevent 和 cudaEvent_t 之间的交互
类型 CUevent 和 cudaEvent_t 是相同的,可以互换使用。
CUarray 和 cudaArray_t 之间的交互
类型 CUarray 和 struct cudaArray * 表示相同的数据类型,可以通过在两种类型之间进行强制转换来互换使用。
为了在 CUDA 运行时 API 函数中使用 CUarray,该函数接受 struct cudaArray *,必须将 CUarray 显式转换为 struct cudaArray *。
为了在 CUDA 驱动程序 API 函数中使用 struct cudaArray *,该函数接受 CUarray,必须将 struct cudaArray * 显式转换为 CUarray 。
CUgraphicsResource 和 cudaGraphicsResource_t 之间的交互
类型 CUgraphicsResource 和 cudaGraphicsResource_t 表示相同的数据类型,可以通过在两种类型之间进行强制转换来互换使用。
为了在 CUDA 运行时 API 函数中使用 CUgraphicsResource,该函数接受 cudaGraphicsResource_t,必须将 CUgraphicsResource 显式转换为 cudaGraphicsResource_t。
为了在 CUDA 驱动程序 API 函数中使用 cudaGraphicsResource_t,该函数接受 CUgraphicsResource,必须将 cudaGraphicsResource_t 显式转换为 CUgraphicsResource。
CUtexObject 和 cudaTextureObject_t 之间的交互
类型 CUtexObject 和 cudaTextureObject_t 表示相同的数据类型,可以通过在两种类型之间进行强制转换来互换使用。
为了在 CUDA 运行时 API 函数中使用 CUtexObject,该函数接受 cudaTextureObject_t,必须将 CUtexObject 显式转换为 cudaTextureObject_t。
为了在 CUDA 驱动程序 API 函数中使用 cudaTextureObject_t,该函数接受 CUtexObject,必须将 cudaTextureObject_t 显式转换为 CUtexObject。
CUsurfObject 和 cudaSurfaceObject_t 之间的交互
类型 CUsurfObject 和 cudaSurfaceObject_t 表示相同的数据类型,可以通过在两种类型之间进行强制转换来互换使用。
为了在 CUDA 运行时 API 函数中使用 CUsurfObject,该函数接受 cudaSurfaceObject_t,必须将 CUsurfObject 显式转换为 cudaSurfaceObject_t。
为了在 CUDA 驱动程序 API 函数中使用 cudaSurfaceObject_t,该函数接受 CUsurfObject,必须将 cudaSurfaceObject_t 显式转换为 CUsurfObject。
CUfunction 和 cudaFunction_t 之间的交互
类型 CUfunction 和 cudaFunction_t 表示相同的数据类型,可以通过在两种类型之间进行强制转换来互换使用。
为了在 CUDA 驱动程序 API 函数中使用 cudaFunction_t,该函数接受 CUfunction,必须将 cudaFunction_t 显式转换为 CUfunction。
CUkernel 和 cudaKernel_t 之间的交互
类型 CUkernel 和 cudaKernel_t 表示相同的数据类型,可以通过在两种类型之间进行强制转换来互换使用。
为了在 CUDA 驱动程序 API 函数中使用 cudaKernel_t,该函数接受 CUkernel,必须将 cudaKernel_t 显式转换为 CUkernel。
函数
- __host__ cudaError_t cudaGetFuncBySymbol ( cudaFunction_t* functionPtr, const void* symbolPtr )
- 获取与入口函数 symbolPtr 匹配的设备入口函数的指针。
- __host__ cudaError_t cudaGetKernel ( cudaKernel_t* kernelPtr, const void* entryFuncAddr )
- 获取与入口函数 entryFuncAddr 匹配的设备内核的指针。
函数
- __host__ cudaError_t cudaGetFuncBySymbol ( cudaFunction_t* functionPtr, const void* symbolPtr )
-
获取与入口函数匹配的设备入口函数的指针symbolPtr.
参数
- functionPtr
- - 返回设备入口函数
- symbolPtr
- - 要搜索的设备入口函数的指针
返回值
描述
在functionPtr中返回与符号对应的设备入口函数symbolPtr.
- __host__ cudaError_t cudaGetKernel ( cudaKernel_t* kernelPtr, const void* entryFuncAddr )
-
获取与入口函数匹配的设备内核的指针entryFuncAddr.
参数
- kernelPtr
- - 返回设备内核
- entryFuncAddr
- - 要搜索内核的设备入口函数的地址
返回值
描述
在kernelPtr与入口函数对应的设备内核entryFuncAddr.
请注意,可能存在多个符号属于不同的翻译单元,它们具有相同的entryFuncAddr已向此 CUDA 运行时注册,因此翻译单元加载和向 CUDA 运行时注册的顺序可能导致kernelPtr中返回不同的指针。 确保唯一性的建议方法是在各自的翻译单元中使用 static 或 hidden 可见性属性来限制 __global__ 设备函数的可见性。
另请参阅
cudaGetKernel (C++ API)