CUDA RUNTIME

本文详细介绍了CUDA运行时库(cudaruntime)与驱动API(cudadriver)的区别,强调了driverAPI的底层特性和灵活性,以及runtimeAPI的易用性。在调用关系上,cudaruntime在首次使用时会触发driverAPI的初始化,并自动管理context。通过示例代码展示了如何在实际应用中使用这两个API。
摘要由CSDN通过智能技术生成

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_runtime.h>

// CUDA驱动头文件
#include <cuda.h>
#include <stdio.h>
#include <string.h>

#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(&current_device));
    printf("current_device = %d\n", current_device);
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洪流之源

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值