TensorRT课程笔记(1)


写在前面

本篇文章程序链接:https://github.com/Shao-junliang/TensorRT-Course-Notes/tree/master/cuda-driver-api

1. 显卡,显卡驱动,nvcc, cuda driver,cudatoolkit,cudnn到底是什么?

  1. 关于显卡驱动与cuda驱动的版本匹配。

  2. 简单了解显卡相关概念:

    • 显卡:GPU
    • 显卡驱动:驱动软件,类比声卡驱动,摄像头驱动;
    • GPU架构:gpu架构指的是硬件的设计方式,例如是否有L1 or L2缓存;
    • CUDA: 其中一种理解是它是一种编程语言(像c++,python等,只不过它是专门用来操控GPU的);
    • cudnn: 这个其实就是一个专门为深度学习计算设计的软件库,里面提供了很多专门的计算函数;
    • CUDAToolkit:这是我们真正需要首先安装的工具包,所谓的装cuda首先指的是它;它里面包含了许多库,例如:cudart, cublas等;
    • 其他涉及到的知识有nvcc与nvidia-smi, 多个 cuda 版本之间进行切换, cuda的安装等;详细请参考: https://zhuanlan.zhihu.com/p/91334380
  3. cuda-driver-api 与 cuda-runtime-api

    • CUDA Driver与CUDA Runtime相比更偏底层,就意味着Driver API有着更灵活的控制,也伴随着更复杂的编程。
    • 因此CUDA driver需要做显式的初始化cuInit(0),否则其他API都会返回CUDA_ERROR_NOT_INITIALIZED
    • 经过初始化后驱动和显卡的信息可以轻松获取:

2. 使用宏定义来检查是否有做cuda初始化

  1. CUDA driver需要做显式的初始化cuInit(0),否则其他API都会返回CUDA_ERROR_NOT_INITIALIZED;
  2. 采用宏定义可以在每次调用API前都检查初始化;
  3. 采用封装带参宏定义使代码更清晰、好调试,养成一种良好的编码习惯也是很重要!

3. context的概念和使用方法

  1. 设备与特定进程相关连的所有状态。比如,写的一段kernel code对GPU的使用会造成不同状态(内存映射、分配、加载的code),Context则保存着所有的管理数据来控制和使用设备。

  2. 上下文管理可以干的事儿:

    • 持有分配的内存列表;
    • 持有加载进该设备的kernel code
    • cpu与gpu之间的unified memory
  3. 如何管理上下文:

    1. 在cuda driver同样需要显式管理上下文
      • 开始时cuCtxCreate()创建上下文,结束时cuCtxDestroy销毁上下文。像文件管理一样须手动开关。用cuDevicePrimaryCtxRetain()创建上下文更好!
      • cuCtxGetCurrent()获取当前上下文;
      • 可以使用堆栈管理多个上下文cuCtxPushCurrent()压入,cuCtxPopCurrent()推出;
      • 对ctxA使用cuCtxPushCurrent()cuCtxCreate()都相当于将ctxA放到栈顶(让它成为current context)
    2. cuda runtime可以自动创建,是基于cuDevicePrimaryCtxRetain()创建的。

4. 内存分配

  1. 统一内存(Unified addressing) ;

  2. 分配线性内存cuMemAlloc()

    • 线性内存:线性内存被组织在单个连续的地址空间中,可以直接以及线性地访问这些内存位置。

    • 内存分配空间以字节为大小,并返回所分配的内存地址

  3. 分配主机锁页内存cuMemAllocHost():

    1. 锁页内存:
    • 定义:页面不允许被调入调出的叫锁页内存,反之叫可分页内存;
      • 优点:快;
      • a. 设备可以直接访问内存,与可分页内存相比,它的读写带宽要高得多;
      • b. 驱动程序会跟踪使用cuMemAllocHost()分配的虚拟内存范围,并自动加速对cuMemcpy()等函数的调用;
      • 使用注意:分配过多锁业内存会减少系统可用于分页的内存量,可能会降低系统性能。因此,在主机和设备之间为数据交换分配临时区域时,最好少用此功能。
    1. 这里是从主机分配内存,因此不是输入device prt的地址,而是一个主机的二级地址。
  4. 内存的初始化cuMemsetD32(CUdeviceptr dstDevice, unsigned int ui, size_t N), 将N个32位值的内存范围设置为指定的值ui。

  5. 内存的释放cuMemFreeHost(): 有借有还 再借不难~

声明: 本文部分内容来源于网络,如有侵权请联系删除。


文章作者: LSJune
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LSJune !
评论
  目录