Ubuntu无root权限安装多版本cuda

1. cuda介绍

CUDA(Compute Unified Device Architecture, CUDA)是由NVIDIA推出的通用并行计算架构。解决的是用更加廉洁的设备资源,实现更高效的并行计算。GPU是显卡的核心芯片,而cuda正是暴露了英伟达开发的GPU的编程接口。

几乎所有的编程语言,不使用特定框架,都只能实现CPU编程——std::thread也是将线程开在CPU中。而不同于每一位程序员都接触过的CPU编程,GPU编程可以使用更多的流处理器更多的线程数

显卡的简化结构

显卡内部,有三级结构:网格(grid), 块(block), 线程(thread)。

每个显卡只有很少的网格,一个核函数目前只能运行在一个网格中,而一个网格里有多个块,每个块包含了若干线程。具体包含了多少,可以使用的deviceQuery来查询,通常是256、1024这样的值。

如何将计算部署在这些块和线程之上呢?这就是核函数kernel function)及其运行时参数runtime parameter)的工作。

2. cuda 两种API对比

img
img

cuda有两种API,Driver API和Runtime API。

从上图可以简单的看出,Runtime是Driver的“更高级”的Layer。既然如此,自然可以得出很多显而易见的结论:Driver API有着更灵活的控制,也存在更高的性能的可能性,当然也伴随着更复杂的编程。

其实两种API的存在,更多也是历史原因。CUDA首次出现的时候,所提供的就是现在被称为“CUDA driver API”,但很快大家发现这套API过于复杂,很多人只是想launch一个kernel,就要写出很多看起来无关的host代,这也直接导致了CUDA runtime API的开发。在CUDA最初的几个版本中(CUDA 3.0之前),的确存在着一些功能只有driver API可以实现,而runtime无法做到的。但现在嘛,,,CUBLAS、CUFFT等这些CUDA库都已经是基于CUDA Runtime开发的了,对于普通用户来说,CUDA runtime基本可以满足你的所有需求。

CUDA driver相比runtime需要做显式的device初始化,以及context、module的管理,这些概念在runtime中是不存在,也是不希望用户关心的。同时CUDA driver API也是“语言无关的”,因为它只需要处理cubin对象。而且其实runtime和driver API之间并没有显著的性能差异

总结一下,只有CUDA driver API可以做的事:

  • CUDA 显式的初始化(拜托,没人想做这种事好吧
  • 获取一些device的信息,比如blcok中最大线程数量,甚至还有video memory的频率等等,具体的可以查看enum CUdevice_attribute,目前有超过100个attribute。还可以获取GPU的内存大小,compute-capable等。
  • 获取目前driver支持的最新CUDA版本
  • 管理Context,包括创建,销毁等一系列操作
  • 管理module

编译方面等还有一些区别。

3. 一些基本概念

NVCC是什么

NVIDIA Cuda compiler driver

就是CUDA开发环境下的C语言编译器。查询nvcc版本我们就知道了tookit的版本。

cudnn

专门为深度学习计算设计的软件库,里面设计了很多专门的计算函数,如卷积等。只是面向一种应用设计的软件库而已。

cuda tookit

由以下组件形成:

  • Compiler: NVCC等
  • tools
  • libraries
  • cuda sample
  • cuda driver
nvidia-smi

全称NVIDIA System Management Interface。是一个基于前面介绍的NVML构建的命令行实用工具,旨在帮助管理和监控NVIDIA GPU设备。

cat /usr/local/cuda/version.txt

这个功能和nvcc -V其实一样。

LIBRARY_PATH和LD_LIBRARY_PATH

这两个路径可以放在一起讨论,

  • LIBRARY_PATH程序编译期间查找动态链接库时指定查找共享库的路径
  • LD_LIBRARY_PATH程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径

两者的共同点是库,库是这两个路径和PATH路径的区别,PATH是可执行文件。

两者的差异点是使用时间不一样。一个是编译期,对应的是开发阶段,如gcc编译;一个是加载运行期,对应的是程序已交付的使用阶段。

配置方法也是类似:

1
export  LD_LIBRARY_PATH=LD_LIBRARY_PATH:XXXX

4. 两种API的匹配

使用cuda时很多人遇到两者不匹配的问题,报错提示CUDA driver version is insufficient for CUDA runtime version.

查询两个API的版本

命令nvidia-smi,可以看到GPU的驱动程序版本,也即对应driver API,后面的版本也是Driver API的版本。

image-20200920154502174
image-20200920154502174

命令nvcc -V,查询的结果对应CUDA Runtime API。

image-20200920154923644
image-20200920154923644
两个API版本不同的解释

CUDA有两个主要的API:runtime(运行时) APIdriver API。这两个API都有对应的CUDA版本(如9.2和10.0等)。

  • 用于支持driver API的必要文件(如libcuda.so)是由GPU driver installer安装的。nvidia-smi就属于这一类API。
  • 用于支持runtime API的必要文件(如libcudart.so以及nvcc)是由CUDA Toolkit installer安装的。(CUDA Toolkit Installer有时可能会集成了GPU driver Installer)。nvcc是与CUDA Toolkit一起安装的CUDA compiler-driver tool,它只知道它自身构建时的CUDA runtime版本。它不知道安装了什么版本的GPU driver,甚至不知道是否安装了GPU driver。

综上,如果driver API和runtime API的CUDA版本不一致可能是因为你使用的是单独的GPU driver installer,而不是CUDA Toolkit installer里的GPU driver installer。

判断两个API是否兼容

进入英伟达的网址,判断两个版本是否兼容。

https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html

重新安装Runtime API(tookit)

如果两者不兼容,解决方案时更改Runtime API,即从上面链接给出的表格中找到与Driver API兼容的Runtime版本。

5. 较好的安装实践

先用nvidia-smi看驱动版本,然后下载对应的cuda版本,然后下载对应的cudnn版本。然后利用conda安装pytorch等软件。

先用nvidia-smi看驱动版本,然后利用conda安装cuda,cudnn和pytorch。

为什么用conda

因为conda不涉及高级权限,而且会安装依赖。

6. Ubuntu无root权限安装多版本cuda

  1. 确定版本信息
  2. 下载cuda tookit的runfile版本(利用wget)
  3. 下载cudnn
  4. sh XXX安装cuda, 按照提示走
  5. 配置用户bash下的环境变量./bashrc,加入
1
2
export PATH=/home/zb/cuda/cuda-8.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/home/zb/cuda/cuda-8.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
  1. source .bashrc让环境变量生效。

7. conda安装cuda

conda所安装的cudatoolkit是cudatoolkit的子集,很方便我们使用,且节省安装的工作量。

参考资料

  1. CUDA教程】一、认识cuda
  2. 浅谈Cuda driver API
  3. 显卡,显卡驱动,nvcc, cuda driver,cudatoolkit,cudnn到底是什么?
  4. 安装cuda