AMD显卡上完美原生运行PyTorch教程,无需容器(Docker)

博主的一些废话

本站的【第一篇正经博文】发布之后,受到了各方的好评,在此非常感谢陈老师的【微博转载】,没有陈老师的转发,我的博客是不可能得到那么高的关注度的。陈老师是杜克大学进化智能中心的主任,是我深度学习方向上的启蒙老师,希望大家也能多多关注【他的微博】【个人主页】,对陈老师研究方向感兴趣的同学也可以考虑报考他的研究生。

非常感谢许多读者对本博客发来的意见和建议,其中出现的最多的两个建议是:
Q1. 使用.tk域名导致分享的链接被微信内置浏览器拦截并重排版,并且重排版以后也无法正确显示。
A1. 现在域名已经改成.net的了,测试了一下不再会被微信内置浏览器拦截。新的博客地址为:https://www.shenjc.net ,旧的域名:https://www.shenjc.tk 依然可以访问,被我URL转发到新的域名了,以后欢迎大家通过新的域名来访问我的博客。
Q2. 博客的功能比较少,没有留言板功能和RSS订阅功能。
A2. 留言板和RSS订阅功能已经上线了。目前留言板还没有开启验证码功能,希望大家不要滥用,请勿发广告。RSS订阅在右下角的黑色小按钮里,或者也可以点击【这个链接】。 再次感谢这些热心读者在没有留言板的状态下,依然通过各种渠道提供了宝贵的反馈意见。
最后,还有一个反馈就是,上一篇博文的废话章节似乎太多了,占据了几乎整篇文章1/3的篇幅,为只想学习如何在AMD显卡上运行PyTorch的读者们带来了一些困扰。以后我会把杂谈类的内容单独分出来,尽量在技术类文章中少讲废话,希望技术类博文能做到干货多,屁话少。

容器真的好难用 [Nothing works in Docker without a struggle]

上一篇博文主要介绍的是如何在容器中运行PyTorch on ROCm,对于直接编译安装则是只给出了大致的思路。限于目前ROCm的开发成熟度,目前在原生环境中编译安装PyTorch需要对本地的ROCm环境进行修改(AMD ROCm software团队承诺在未来版本中会解决这个问题)。这就导致了这篇今天可以正常运行的教程,在未来可能就会过时,这也是我在上一篇博文中没有给出原生环境安装step by step的教程的主要原因。不过,我也没有想到有不少读者也和我一样,对容器有些不太习惯,希望能在原生环境中运行,最终促生了这篇博文。
说实话,容器是一种比较偷懒的办法,最主要的工作是由AMD ROCm software团队帮我们完成了。虽然方便,但是缺点也很明显:

  1. 需要依赖AMD ROCm software团队针对PyTorch的新版本及时发布新的容器镜像,这往往会落后于PyTorch主枝,无法在第一时间享受到PyTorch版本更新所提供的新功能和最新优化。
  2. 同样的,也只能选择镜像中已有的Python版本,无法使用自己用的最顺手的Python版本。
  3. 在AMD ROCm software团队发布的镜像中,只有root用户才能使用PyTorch,导致在容器中运行PyTorch脚本生成的输出文件,文件owner都是root,很容易把项目里的文件权限搞得一塌糊涂。
  4. PyTorch最大的魅力在于可以像普通的Python程序和脚本一样调试,配合PyCharm、Visual Code等工具调试起来非常高效且符合直觉。在容器中部署PyTorch则无法和原生环境中的这些调试环境联动。当然,也可以选择在容器中安装那些东西,不过正如标题所说,Nothing works in Docker without a struggle,既然都要struggle了,那还不如折腾怎么让PyTorch在原生的环境中运行。
  5. 很多读者和我一样,在以前使用容器的过程中有一些不愉快的经验,对于容器的抵触情绪暂时还无法消散。

在这里和做Cloud native、Kubernetes等容器技术的读者说一声抱歉,我真诚的认为容器技术是一项很好的技术,只是目前阶段,在有选择的前提下,容器还不是我的第一选择。

准备阶段 [Preparation]

本文假设你已经参考【上一篇博文】中的教程,正确的配置了github代理加速(建议,可选)和AMD ROCm平台(必须)。

  1. 由于编译需要比较长的时间,建议关闭Ubuntu系统的睡眠功能,以免在编译过程中意外进入睡眠状态。顺便把猫子从桌上赶走。编译到一半被猫子给关了,真是晕倒。

  2. 运行以下命令,确保ROCm的包已经安装完全:

    1
    2
    sudo apt update
    sudo apt install rock-dkms rocm-dev rocm-libs miopen-hip hipsparse hip-thrust rccl
  3. 安装编译所需要的一些工具,编译完成后可以选择删除:

    1
    sudo apt install git python-pip libopenblas-dev cmake libnuma-dev autoconf build-essential ca-certificates curl libgoogle-glog-dev libhiredis-dev libiomp-dev libleveldb-dev liblmdb-dev libopencv-dev libpthread-stubs0-dev libsnappy-dev sudo vim libprotobuf-dev protobuf-compiler
  4. 安装anaconda(可选,建议)。具体步骤请参考【这个链接】。如果安装了anaconda,使用以下命令创建并进入pytorch专用环境:

    1
    2
    conda create --name pytorch python=3.6
    source activate pytorch
  5. 安装PyTorch的Python依赖包:

    1
    pip install enum34 numpy pyyaml setuptools typing cffi future hypothesis

编译安装PyTorch on ROCm [Compile from scratch]

  1. 正如最开始说的,目前ROCm平台还存在一些缺陷,因此编译PyTorch需要修改ROCm平台。修改后的ROCm平台可能不能编译或者运行其他深度学习框架。在root权限下运行以下命令:

    1
    2
    3
    4
    sed -i 's/find_dependency(hip)/find_dependency(HIP)/g' /opt/rocm/rocsparse/lib/cmake/rocsparse/rocsparse-config.cmake
    sed -i 's/find_dependency(hip)/find_dependency(HIP)/g' /opt/rocm/rocfft/lib/cmake/rocfft/rocfft-config.cmake
    sed -i 's/find_dependency(hip)/find_dependency(HIP)/g' /opt/rocm/miopen/lib/cmake/miopen/miopen-config.cmake
    sed -i 's/find_dependency(hip)/find_dependency(HIP)/g' /opt/rocm/rocblas/lib/cmake/rocblas/rocblas-config.cmake

    请各位读者注意,若新版的ROCm平台修复此问题,请忽略该步骤。

  2. 拉取PyTorch的源代码。这里建议拉取AMD ROCm software团队的fork仓库:

    1
    git clone https://github.com/ROCmSoftwarePlatform/pytorch.git

    这个分支会定期Merge来自主支的修改。理论上来说,PyTorch的官方分支也是可以在ROCm平台上编译的,但是我没有试过,不保证可行,如果你希望体验PyTorch最新的功能,可以尝试使用官方仓库:

    1
    git clone https://github.com/pytorch/pytorch.git

    如果碰到什么问题,欢迎各位读者在留言区交流。

  3. 拉取PyTorch的子模块:

    1
    2
    cd pytorch
    git submodule update --init --recursive

    正常情况下,步骤2和步骤3大约需要下载500MB的数据。

  4. 配置你的GPU类型。目前ROCm支持gfx803, gfx900和gfx906这三种GPU。在【上一篇博文】中可以找到各个GPU芯片所对应的类型。如果不能确定,可以通过以下命令获取/opt/rocm/bin/rocm_agent_enumerator。通过设置环境变量,指明编译针对的GPU类型,例如我的RX 580为gfx803,则我的设置为:export PYTORCH_ROCM_ARCH=gfx803

  5. 删除conda环境中的ld(可选,仅针对使用anaconda)。不知道为什么,conda环境中自己有一个ld,会覆盖系统中自带的/usr/bin/ld,会导致编译出问题。通过重命名的方式使其不影响编译:

    1
    2
    3
    cd ~/anaconda3/envs/pytorch/compiler_compat
    mv ld ld-tmp
    cd -

    在编译完成后可以把它改回来。

  6. 使用AMD提供的脚本将PyTorch中的CUDA函数白嫖重用为ROCm中的hip函数。

    1
    python tools/amd_build/build_amd.py

    ROCm的这个'hipify'功能真的很强大,避免了重写海量PyTorch底层CUDA函数的巨大工作量。hipify的存在使得ROCm平台具有在短期内追赶CUDA的潜力。

  7. 编译安装PyTorch:

    1
    2
    export USE_NINJA=1 # 可选
    USE_ROCM=1 USE_LMDB=1 BUILD_CAFFE2_OPS=0 BUILD_TEST=0 USE_OPENCV=1 MAX_JOBS=N python setup.py install

    其中,N为编译时使用的线程数。N越大则编译速度越快,但是要注意的是,请不要把N设的太大,在编译过程中,进程最高会占用5GB的内存,因此请保证5*N小于你的内存总量。否则内存要是超出了可是会死机的。如果因为N设置过大导致编译失败,请使用命令python setup.py clean清空编译环境后再重新编译。

  8. 去休息一下,喝一杯咖啡。编译会比较耗时间。在此期间请不要使用内存占用过高的程序,例如Chrome,避免因为内存不足导致编译失败。

  9. 编译安装torchvision:

    1
    2
    3
    4
    git clone https://github.com/pytorch/vision
    cd vision
    python setup.py install
    cd ..
  10. 运行PyTorch测试。

    1
    PYTORCH_TEST_WITH_ROCM=1 python test/run_test.py --verbose

    可以发现,通过的测试数量比上次Docker安装的更加多了。说明这次的PyTorch安装功能更加完整,理论上能提供更好的开发体验。

  11. Enjoy! 将~/anaconda3/envs/pytorch/bin/python设置为你开发环境的解释器,你甚至感受不到你用的不是CUDA!

最后

希望大家能够多多关注AMD ROCm,我认为这是一个很有潜力的平台。再加上最近AMD的势头不错,会在这个领域继续加大投入,CUDA将会面对激烈的正面竞争。在Reddit上,有用户汇报AMD最新的Radeon VII在Tensorflow benchmark上超过了同价位的RTX 2080大约10%至20%,FP16和FP32都是如此。Radeon VII在没有专门针对FP16设计Tensorcore的不利条件下依然力克同价位的竞品,再加上用料十足的16GB HBM2显存,足以体现AMD在产品方面的诚意。目前挡在Radeon Technology Group和深度学习之间的,可能只有部署难度了。希望这篇博客可以帮助到各位,麻烦AMD公关部门看到这篇文章,主动结一下广告费,谢谢(Just kidding)。