CUDA RUNTIME

CUDA RUNTIME,第1张

cuda runtime是以cuda driver为基准开发的运行时库,driver API更为底层一些,对一般用户不是很友好,例如需要做显式的device初始化,以及context、module的管理。


但是使用更为灵活,提供一些runtime API所没有的功能,毕竟runtime API的功能都是包装driver 的功能实现的。


而runtime API把driver API包装了一些,将很多原本需要代码编写的步骤(比如说上面的device初始化)自动完成了比如自动管理的context,因此会更加容易上手。


 cuda runtime与cuda driver调用关系如下:

注意:cuda driver是跟随NVIDIA GPU Driver一起发布的,也就是说在安装显卡驱动时就已经安装了cuda driver,cuda driver的库文件和头文件分别是libcuda.so、cuda.h;cuda runtime是在安装cuda-toolkit时安装的,cuda runtime的库文件和头文件分别是libcurt.so、cuda_runtime.h。


  1. 当调用第一个cuda runtime api时会触发cuda driver级别的初始化等 *** 作,比如触发cuInit;
  2. 当在调用cuda runtime api时,如果当前api需要CUcontext,则会默认调用cuDevicePrimaryCtxRetain函数关联一个CUcontext,后续依赖CUcontext的cuda runtime api也会默认使用该CUcontext;

注意:cu开头的是cuda driver api函数,cuda开头的是cuda runtime api函数。


示例代码:


// CUDA运行时头文件
#include 

// CUDA驱动头文件
#include 
#include 
#include 

#define checkRuntime(op)  __check_cuda_runtime((op), #op, __FILE__, __LINE__)

bool __check_cuda_runtime(cudaError_t code, const char* op, const char* file, int line){
    if(code != cudaSuccess){    
        const char* err_name = cudaGetErrorName(code);    
        const char* err_message = cudaGetErrorString(code);  
        printf("runtime error %s:%d  %s failed. \n  code = %s, message = %s\n", file, line, op, err_name, err_message);   
        return false;
    }
    return true;
}

int main(){

    // 当前context为空
    CUcontext context = nullptr;
    cuCtxGetCurrent(&context);
    printf("Current context = %p,当前无context\n", context);

    // 首次调用cuda runtime api, 触发cuInit()
    int device_count = 0;
    checkRuntime(cudaGetDeviceCount(&device_count));
    printf("device_count = %d\n", device_count);

    // cuda runtime api使用setdevice来控制当前上下文
    // 注意,context是线程内作用的,其他线程不相关的, 一个线程一个context stack
    int device_id = 0;
    printf("set current device to : %d,这个API依赖CUcontext,触发创建并设置\n", device_id);
    // 首次调用依赖CUcontext的cuda runtime api, 
    // 触发cuDevicePrimaryCtxRetain函数关联一个CUcontext。


// 注意: 由于set device函数是"第一个执行的需要context的函数", // 所以会触发执行cuDevicePrimaryCtxRetain函数, 并设置当前context,这一切都是默认执行的。


// cudaGetDeviceCount是一个不需要context的函数, 所以没有触发执行cuDevicePrimaryCtxRetain函数 // 但是绝大部分runtime api都是需要context的,所以第一个执行的cuda runtime函数,会创建context并设置上下文。


checkRuntime(cudaSetDevice(device_id)); // 可以获取到非空的context cuCtxGetCurrent(&context); printf("SetDevice after, Current context = %p,获取当前context\n", context); int current_device = 0; checkRuntime(cudaGetDevice(¤t_device)); printf("current_device = %d\n", current_device); return 0; }

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/589657.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-13
下一篇 2022-04-13

发表评论

登录后才能评论

评论列表(0条)

保存