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

时间:2011-09-23 21:09:41

标签: cuda

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

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

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

引用NVIDIA的文档

  

CUDA Runtime API调用在CUDA Driver API CUcontext上运行   绑定到当前主机线程。

     

如果没有绑定到当前的CUDA Driver API CUcontext   CUDA Runtime API调用时的线程需要一个   CUcontext然后CUDA Runtime将隐式创建一个新的CUcontext   在执行呼叫之前。

     

如果CUDA Runtime创建了CUcontext,那么CUcontext将是   使用CUDA Runtime API指定的参数创建   函数cudaSetDevice,cudaSetValidDevices,cudaSetDeviceFlags,   cudaGLSetGLDevice,cudaD3D9SetDirect3DDevice,   cudaD3D10SetDirect3DDevice和cudaD3D11SetDirect3DDevice。注意   如果它们是cudaErrorSetOnActiveProcess,这些函数将失败   当CUcontext绑定到当前主机线程时调用。

     

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

     

如果CUDA运行时创建了CUcontext,那么就是CUDA运行时   将减少函数中CUcontext的引用计数   cudaThreadExit。如果CUcontext是由CUDA驱动程序API创建的(或   由CUDA运行时API库的单独实例创建),   然后CUDA运行时不会增加或减少参考   该CUcontext的计数。

     

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

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

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

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

1 个答案:

答案 0 :(得分:3)

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

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

您可以使用驱动程序API中的上下文/线程管理功能(例如cuCtxPopCurrent()/ cuCtxPushCurrent())来使用来自其他线程的上下文。

你可以打电话给cudaFree(0);强制这种懒惰的初始化发生。

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