运行时API应用程序中的cuda上下文创建和资源关联

ash*_*ash 6 cuda

我想了解如何在cuda运行时API应用程序中创建cuda上下文并与内核相关联?

我知道它是由驱动程序API在引擎盖下完成的.但我想了解创作的时间表.

首先我知道cudaRegisterFatBinary是第一个cuda api调用,它在运行时注册了一个fatbin文件.接下来是一些cuda函数注册API,它们在驱动程序层中调用cuModuleLoad.但是如果我的Cuda运行时API应用程序调用cudaMalloc,那么如何将指针提供给与上下文相关联的函数,我相信应该事先创建它.如何获得这个已经创建的上下文的句柄并将未来的运行时API调用与它相关联?请揭开内部运作的神秘面纱.

引用NVIDIA的文档

CUDA运行时API调用在绑定到当前主机线程的CUDA驱动程序API CUcontext上运行.

如果在需要CUcontext的CUDA运行时API调用时没有绑定到当前线程的CUDA驱动程序API CUcontext,则CUDA运行时将在执行调用之前隐式创建新的CUcontext.

如果CUDA运行时创建CUcontext,则将使用CUDA运行时API函数cudaSetDevice,cudaSetValidDevices,cudaSetDeviceFlags,cudaGLSetGLDevice,cudaD3D9SetDirect3DDevice,cudaD3D10SetDirect3DDevice和cudaD3D11SetDirect3DDevice指定的参数创建CUcontext.请注意,如果在CUcontext绑定到当前主机线程时调用它们,则这些函数将失败并使用cudaErrorSetOnActiveProcess.

CUcontext的生命周期由引用计数机制管理.CUcontext的引用计数最初设置为0,并通过cuCtxAttach递增并递减cuCtxDetach.

如果CUDA运行时创建了CUcontext,则CUDA运行时将减少函数cudaThreadExit中该CUcontext的引用计数.如果CUcontext由CUDA驱动程序API创建(或由CUDA运行时API库的单独实例创建),则CUDA运行时将不会递增或递减该CUcontext的引用计数.

所有CUDA运行时API状态(例如,全局变量的地址和值)都与其基础CUcontext一起传播.特别是,如果CUcontext从一个线程移动到另一个线程(使用cuCtxPopCurrent和cuCtxPushCurrent),那么所有CUDA Runtime API状态也将移动到该线程.

但我不明白的是cuda运行时如何创建上下文?用于此的API调用是什么?nvcc编译器是否在编译时插入一些API调用来执行此操作,还是完全在运行时完成?如果前者是真的那么运行时API用于此上下文管理?后来的确如何完成呢?

如果上下文与主机线程相关联,我们如何访问此上下文?它是否自动与线程处理的所有变量和指针引用相关联?

最终如何在上下文中完成模块加载?

Arc*_*are 3

CUDA 运行时维护要加载的模块的全局列表,并在每次将使用 CUDA 运行时的 DLL 或 .so 加载到进程中时添加到该列表中。但在创建设备之前,模块实际上并未加载。

上下文创建和初始化是由 CUDA 运行时“延迟”完成的——每次调用像 cudaMemcpy() 这样的函数时,它都会检查 CUDA 是否已初始化,如果没有,它会创建一个上下文(在先前由 cudaSetDevice() 指定的设备,或者如果从未调用 cudaSetDevice() 则为默认设备)并加载所有模块。从那时起,上下文就与该 CPU 线程关联,直到它被 cudaSetDevice() 更改为止。

您可以使用驱动程序 API 中的上下文/线程管理函数(例如 cuCtxPopCurrent()/cuCtxPushCurrent())来使用来自不同线程的上下文。

您可以调用 cudaFree(0); 强制进行这种惰性初始化。

我强烈建议在应用程序初始化时这样做,以避免竞争条件和未定义的行为。继续并尽早在您的应用程序中枚举并初始化设备;完成后,在 CUDA 4.0 中,您可以从任何 CPU 线程调用 cudaSetDevice(),它将选择由初始化代码创建的相应上下文。