【CUDA编程】【4】【3.Programming Interface】【3.2.CUDA Runtime】【3.2.1.Initialization】

CUDA Runtime,Initialization

Posted by x-jeff on October 26, 2024

【CUDA编程】系列博客参考NVIDIA官方文档“CUDA C++ Programming Guide(v12.6)”
本文为原创文章,未经本人允许,禁止转载。转载请注明出处。

1.CUDA Runtime

CUDA runtime在cudart库中实现。该库可以以静态链接(通过cudart.liblibcudart.a)或动态链接(通过cudart.dlllibcudart.so)的方式与应用程序链接。

CUDA runtime的所有入口点都以cuda作为前缀。

2.Initialization

在运行时,会为系统中的每个device创建一个CUDA context。这个context是该device的primary context,并且该context会在该device上第一个函数被调用时被初始化。该context在应用程序的所有host线程之间是共享的。在创建context时,如果需要,device代码将进行即时编译并加载到device内存中。

在CUDA 12.0之后,cudaSetDevice()可用于指定device并自动执行CUDA运行时和primary context的初始化。在CUDA 12.0之后,也可以调用cudaInitDevice()单独执行CUDA运行时和primary context的初始化。如果没有显式的指定device并初始化,将默认使用device 0并根据需要进行自初始化(self-initialize)。

而在CUDA 12.0之前,cudaSetDevice()只能用于指定device,没有初始化的作用,此时通常使用cudaFree(0)来执行初始化。cudaFree(void *devPtr)原本的功能是用于释放显存,仅有一个参数,是一个指针,指向需要释放的内存。如果devPtr为0,则什么操作都不会做,但如果cudaFree(0)是第一个被调用的函数,此时就会默认执行初始化,从而达到初始化的目的。

如果我们不在device代码的一开始显式的初始化,那就会等到第一个真正被调用的函数时才执行默认初始化,这可能会影响效率或有其他风险。此外,如果在没初始化的状态下调用CUDA接口,将会导致未定义行为。

当host线程调用cudaDeviceReset()时,将销毁host线程当前操作的device的primary context。任何一个将该device作为当前device的host线程将在下一个运行时函数调用的时候创建该device的一个新primary context。

注意:

CUDA接口使用全局状态,该状态在host程序启动时初始化,并在host程序终止时销毁。CUDA运行时和驱动程序都无法检测到此状态是否无效,因此在程序启动期间或在main函数终止之后(无论是显式还是隐式)使用这些接口中的任何一个都将导致未定义行为。

错误处理和版本管理部分的运行时函数不会初始化运行时。