ysl2 / .dotfiles

My dotfiles
2 stars 0 forks source link

cuda和cudnn相关问题 #55

Open ysl2 opened 5 months ago

ysl2 commented 5 months ago

手动在家目录下面安装cuda和cudnn

场景:

  1. 假设正在跑很多别人的深度学习代码,但是它们分别依赖于不同的cuda和cudnn版本,而如果从系统级别安装,只能固定一个版本,这种情况明显不适合从系统层面安装cuda和cudnn
  2. 假设在实验室的公用服务器上面,没有管理员权限,而cuda和cudnn的版本是固定的(即管理员从系统层面安装的),也没sudo权限修改,并且就算有,也会修改共用的cuda和cudnn,有可能导致别人没办法跑代码

以下方法,考虑到Tensorflow对版本依赖性更强,更易出问题,下面的例子的第一步中是按照Tensorflow来进行的,后面的步骤Pytorch和Tensorflow通用。选择的cuda版本是10.2,对应的cudnn版本是v8.7.0。

  1. 确定要安装的cuda和cudnn版本。pytorch可能可以省略这一步(因为pytorch出问题比较少,基本上按照官网命令就可以,所以没有针对pytorch查过具体的cuda和cudnn版本)。假设需要跑tensotflow代码,应该先从官网找到版本匹配关系。通过查找所需要的版本,已经能确定了具体需要安装哪个版本的cuda和cudnn。然后进入到下一步。

    https://tensorflow.google.cn/install/source?hl=en#tested_build_configurations

  2. 根据上面的版本信息,手动安装对应版本的cuda。下面的例子选择了cuda 10.2版本。

    首先去cuda官网,下载对应的安装包。下载出来的文件名字类似于cuda_10.2.89_440.33.01_linux.run这样后缀是run的文件,可能几百兆。

    然后任意指定目录的 上级目录 需要预先手动创建好。比如下面的例子中,选择了~/.vocal/bin/cuda-10.2。这个路径一开始并不存在。需要先mkdir ~/.vocal/bin创建上级目录。

    之后通过下面的命令,执行上面的run文件,安装cuda到指定的目录里面

    # 非root安装示例
    sh cuda_10.2.89_440.33.01_linux.run --silent --toolkit --toolkitpath=$HOME/.vocal/bin/cuda-10.2 --defaultroot=$HOME/.vocal/bin/cuda-10.2
    
    # (1) 如果上面这一步出现`log file not open`,说明是之前有人乱搞过cuda,导致产生了日志文件,
    # 并且还在系统目录里面,权限不够,所以让服务器管理员用sudo把这个log file删掉,再重复一次上面的步骤
    # (2) 如果上面这一步提示gcc版本不匹配,因为是手动安装的cuda,而cuda依赖于系统里面的gcc。gcc版本太低也不行。
    # cuda 10.2的话,依赖gcc 8就可以,gcc7的话不行。需要想办法搞一个gcc 8出来。解决方法如下:
    # 方式1. (需要sudo权限,因此需要管理员操作)用下面的命令暂时切换系统层面所用的gcc版本。这样会影响到其他人
    sudo update-alternatives --config gcc
    # 方式2. 把/usr/bin/gcc-8 (如果有的话,一般服务器上会有多个gcc版本)链接到~/.vocal/bin/gcc,即我们自己家目录下面的gcc来作为默认的gcc。
    ln -s /usr/bin/gcc-8 ~/.vocal/bin/gcc
    # 之后,需要在`~/.bashrc`中,把自己这个gcc提前,这样系统找gcc的时候从头开始遍历`$PATH`,会先找到自己的gcc作为默认gcc
    export PATH="$HOME/.vocal/bin:$PATH"  # 在`~/.bashrc`文件里面添加
    # 解决完gcc问题后,再重复上面的非root安装cuda的方法
    
    # 在安装好cuda之后,需要把自己的cuda放到`$PATH`变量的开头,将自己的cuda作为优先找到的,从而规避掉系统的cuda
    # 在~/.bashrc文件里添加环境变量(加入这两句话)
    export PATH="$HOME/.vocal/bin/cuda-10.2/bin:$PATH"
    export LD_LIBRARY_PATH="$HOME/.vocal/bin/cuda-10.2/lib64"
    # 下面这个是把cuda的动态链接库也能让系统发现到,不然只能调用自己的cuda可执行文件,但是对应的库找不到的话,也会出问题。
  3. 通过第一步确定的cudnn版本,安装对应的cudnn。注意cudnn的版本,同时也是跟cuda版本绑定的。(比如cudnn v8.7.0,可能有对应cuda 10或者11或者12类似的情况),所以需要确定到底需要支持哪个cuda版本的cudnn版本。这里假设对应的版本是cudnn 8.7.0,对应的cuda是10.2

    也是通过官网安装cudnn。需要先注册一个账号。不过如果通过下面的wget,或许可以直接下载下来。注意同时需要确定cudnn和cuda的版本号

    wget -c https://developer.download.nvidia.com/compute/redist/cudnn/v8.7.0/local_installers/10.2/cudnn-linux-x86_64-8.7.0.84_cuda10-archive.tar.xz
    
    # 解压tgz文件
    tar xvf 文件名.tgz

关于下面步骤的解释是:本质上cudnn可以理解为是cuda的一个增强包。可以发现,cudnn实际上并不包含任何可执行文件,而只有动态链接库。所以只需要cudnn的这些链接库,能让系统发现到即可。 因此有两种方案,一种是,找个存放cudnn这些库的路径,然后把这个路径加到上面那个LD_LIBRARY_PATH变量里面,这样系统也能发现到。 另一个方案是,直接把cudnn跟cuda放到一起。这里选择这个方案,如下:

将解压出来的文件夹中的include子文件夹和lib64子文件夹里的内容,分别移动到上述第二步指定的 cuda 安装路径下面对应的include文件夹和lib64(或者lib)文件夹下面。

下面这一步,如果遇到问题了,再继续进行。如果没遇到问题就不用管。可以先看一下:

注意:如果之前 cudnn 的include子文件夹里面包含so.7结尾的文件(比如libcudnn.so.7),需要将这些移动后的文件位置(对应于$HOME/.vocal/cuda-10.2/include/libcudnn.so.7)创建软连接到$HOME/.vocal/bin/cuda-10.2/lib64/libcudnn.so.7。不然有可能依然报错说找不到libcudnn.so.7。也就是说,libcudnn.so.7这个需要include文件夹和lib文件夹都有一份。具体原因没有再研究过了。

后面如果需要多个版本的cuda和cudnn,同样可以安装其他版本的cuda和cudnn,到比如~/.vocal/bin/cuda-12.1这个地方,然后只需要改一下~/.bashrc里面的$PATH$LD_LIBRARY_PATH,再重启一下bash。这样就能切换过去。更进一步地,可以直接把指定$PATH在前面附加成通用的~/.vocal/bin/cuda,然后通过软连接的方式,任意把某个cuda版本链接到~/.vocal/bin/cuda,这样就不用重启bash了,可以任意切换cuda版本。

ysl2 commented 4 months ago

Linux 内核版本更新导致nvidia驱动挂了

场景:运行nvidia-smi命令的时候,报错:NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

原因:缺少当前内核的头文件,这通常发生在内核更新之后。

sudo apt install linux-headers-"$(uname -r)"

Ref: https://zhuanlan.zhihu.com/p/89714824

sudo apt install dkms
# 下面这条命令有可能报错找不到`linux-headers-xxxx-amd64`。此时需要通过apt安装一下。
sudo dkms install -m nvidia -v 418.87.00

其中,418.87.00 是之前安装 nvidia 驱动的版本号,可通过下面方法查到:

# 如果下面这条命令显示的是`nvidia-current-418.87.00`,那还需要将其软连接到`/usr/src/nvidia-418.87.00`
ls /usr/src | grep nvidia