CUDA Driver API 与 CUDA Runtime API

作者:罗上文,微信:Loken1,公众号:FFmpeg弦外之音

CUDA 里有两套 API,Driver API 与 Runtime API,如下:

1-1

Driver API 使用起来比较繁琐,但它允许我们更详细地控制GPU的行为。Runtime API 是基于 Driver API 封装后的高层接口,可以自动管理上下文,开发更简单。

这两套 API 有很多函数是类似的,如下:

Driver API Runtime API 函数作用
cuMemAlloc() cudaMalloc() 申请显卡内存
cuMemFree() cudaFree() 释放显卡内存
cuMemcpy() cudaMemcpy() 拷贝内存

市面上很多 CUDA 编程的书,例如《CUDA 编程基础与实践》,都是讲 Runtime API 的,讲 Driver API 的书相对较少,而 FFmpeg 里用的恰恰是 CUDA Driver API。

所以当你看完《CUDA 编程基础与实践》,想去 FFmpeg 代码里搜 cudaMalloc() 关键词,会发现搜不到,这是因为 FFmpeg 根本没用到 CUDA Runtime API


通俗地理解 CUDA 的 Driver API 与 Runtime API

这两套 API 实际上就是两个库,如下:

Windows Linux
Driver API nvcuda.dll libcuda.so
Runtime API cudart64_101.dll libcudart.so

Driver API 库是在安装显卡驱动的时候装的,它的完整路径是 C:\Windows\System32\nvcuda.dll。Runtime API 库是在安装 CUDA Toolkit 的时候装的,它的完整路径是 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin

提醒:显卡驱动 与 CUDA Toolkit 是两个东西。


CUDA Runtime API 入门示例

文件名 cuda_runtime.cu
#include <stdio.h>
#include <cuda_runtime.h>

int main(int argc, char **argv)
{
    printf("CUDA Runtime API !\n");
    float *d_A;
    cudaMalloc((float**)&d_A, 1024);
    return 0;
}

编译代码:

nvcc -G -Xcompiler "/Zi" -arch=sm_75 -lcudart -o cuda_runtime.exe cuda_runtime.cu

-G 选项是生成 CUDA 代码的调试信息

-Xcompiler "/Zi" 是让 nvcc 把这个 /Zi 选项传递给 MSVC 的 cl.exe 编译器,生产 C 代码的 PDB 调试信息

-lcudart 是链接 cudart64_101.dll 动态库,如果我们不加这个选项,它默认用的是 cudart_static.lib 静态库。

然后我们用 dumpbin 查看一下 cuda_runtime.exe 的依赖

dumpbin /dependents cuda_runtime.exe

1-2

可以看到,已经成功链接了 cudart64_101.dll


我们用 WinDbg 来验证一下 cudaMalloc() 是不是 cudart64_101.dll 动态库里面的函数,WinDbg 命令如下:

  1. bu cuda_runtime!main,在入口设置断点
  2. p,Step over
  3. t,跳进去 cudaMalloc() 函数内部
  4. k,展示调用栈

1-3

可以看到代码跑进了 cudart64_101.dll 动态库。


如果我们编译的时候去掉 -lcudart 选项,那就会使用 cudart_static.lib 静态库 来代替 cudart64_101.dll 动态库。cudaMalloc() 是以静态库的方式插入 exe 文件的,这样 cuda_runtime.exe 就不会依赖 cudart64_101.dll

这时候 WinDbg 的 k 命令展示的调用栈如下:

1-4

去掉 -lcudart 选项 后, cudaMalloc() 函数是属于 cuda_runtime.exe 模块的,而不是属于 cudart64_101.dll 模块的


CUDA Driver API 入门示例

文件名 cuda_driver.cu
#include <stdio.h>
#include <cuda.h>

int main(int argc, char **argv)
{
    printf("CUDA Driver API !\n");
    CUdeviceptr d_A;
    cuMemAlloc(&d_A, 1024);  
    return 0;
}

编译代码:

nvcc -G -Xcompiler "/Zi" -arch=sm_75 -lcuda -o cuda_driver.exe cuda_driver.cu

-lcuda 是链接 nvcuda.dll 动态库,CUDA Driver API 没有静态库,只有动态库。然后我们用 dumpbin 查看一下 cuda_driver.exe 的依赖

dumpbin /dependents cuda_driver.exe

1-2

可以看到,已经成功链接了 nvcuda.dll


我们再用 WinDbg 来验证一下 cuMemAlloc() 是不是 nvcuda.dll 动态库里面的函数,WinDbg 命令如下:

  1. bu cuda_driver!main,在入口设置断点
  2. p,Step over
  3. t,跳进去 cuMemAlloc() 函数内部
  4. k,展示调用栈

1-3

可以看到代码跑进了 nvcuda.dll 动态库。我们也可以用 lm a @rip 命令查看当前代码跑到哪个模块,可以看到 nvcuda.dll 的完整路径,如下:

1-7


虽然 CUDA Runtime API 好用,但它需要安装 CUDA Toolkit,依赖比较重。FFmpeg 代码里用的都是 CUDA Driver API,所以 FFmpeg 并不依赖 cudart64_101.dll

市面上关于 CUDA Driver API 的资料非常少,推荐两本书给读者学习。.

  • 《CUDA专家手册:GPU编程权威指南》- 苏统华
  • CUDA Driver API 官方手册

FFmpeg书籍版权所属@罗上文 2025 all right reserved,powered by Gitbook该文件修订时间: 2026-08-14 16:18:30

results matching ""

    No results matching ""