之前嘗試復現學姐前幾年的一個作業,但是因為框架有點古老而作罷,
然鵝,自己的實驗結果一直跑得十分奇怪,為了去學姐的代碼中尋找參考,今天再次進行了嘗試,
我的需求是安裝Tensorflow_gpu_1.6.0(文中簡稱TensorFlow),目前機器已配置cuda11和cuda10,非root用戶,
- 前置疑問
- Q1: 為什么安裝TensorFlow需要重裝CUDA?
- Q2: nvidia-smi和nvcc -V顯示的不是同一版本CUDA?
- Q3: 用conda裝CUDA不可以嗎?
- 結論
- 0 安裝之前——檢查機器配置(非root用戶)
- 查詢目標配置
- 檢查機器配置
- 安裝順序
- 1 安裝gcc
- 1.1 下載gcc (以gcc6.4.0為例)
- 1.2 configure
- 1.3 編譯
- 1.4 安裝
- 1.4.1 覆寫路徑
- 1.4.2 檢查gcc設定
- 2 安裝CUDA
- 2.1 給cuda可執行權限
- 2.2 執行安裝
- 2.3 卸載CUDA
- 3 安裝cuDNN
- 3.1 解壓安裝檔案
- 3.2 拷貝檔案到cuda
- 3.3 添加權限
- 3.4 配置用戶環境變數
- 4 安裝TensorFlow
- 5 檢測新環境
前置疑問
Q1: 為什么安裝TensorFlow需要重裝CUDA?
當我安裝完畢并運行Tensorflow_gpu_1.6.0時,出現了以下錯誤:
ImportError: libcublas.so.9.0: cannot open shared object file: No such file
這意味著TensorFlow需要對應版本的CUDA,對于CUDA、cuDNN和TensorFlow的關系,知乎有回答寫得很好:
CUDA看作是一個作業臺,上面配有很多工具,如錘子、螺絲刀等,
cuDNN是基于CUDA的深度學習GPU加速庫,有了它才能在GPU上完成深度學習的計算,
它就相當于作業的工具,比如它就是個扳手,但是CUDA這個作業臺買來的時候,并沒有送扳手,想要在CUDA上運行深度神經網路,就要安裝cuDNN,就像你想要擰個螺帽就要把扳手買回來,這樣才能使GPU進行深度神經網路的作業,作業速度相較CPU快很多,
基本上所有的深度學習框架都支持cuDNN這一加速工具,例如:Caffe、Caffe2、TensorFlow、Torch、Pytorch、Theano等,
Q2: nvidia-smi和nvcc -V顯示的不是同一版本CUDA?
來自CW大佬的文章,知道只要 nvcc -V 顯示的版本低于 nvidia-smi 顯示版本就沒有問題,
-
CUDA有runtime API 和 driver API,而nvcc -V顯示的是前者版本,nvidia-smi顯示的是后者版本,
-
nvidia-smi展示的 driver API 代表機器能夠支持的最高版本CUDA,如果driver (nvidia-smi)的版本低于runtime (nvcc -V)版本,通常不會出現問題,
-
產生原因:安裝CUDA可以通過CUDA Toolkit installer 或 GPU driver installer,如果使用了單獨的GPU driver installer來安裝CUDA,就可能會出現版本不一致的現象,而通過CUDA Toolkit installer安裝則會保持一致,
Q3: 用conda裝CUDA不可以嗎?
我嘗試了通過conda安裝對應的CUDA9.0 以及cuDNN,安裝程序很順利,但Tensorflow并不能跑起來,提示缺少對應的.so檔案,而在/usr/local 下也并沒有找到我裝的cuda9.0,
參考知憾訓答 , pytorch如何尋找CUDA:
- 先取默認 cuda 安裝目錄 /usr/local/cuda
- 如默認目錄不存在(例如安裝原生 cuda 到其他自定義位置),那么搜索 nvcc 所在的目錄
- 如果 nvcc 不存在,那么直接尋找 cudart 庫檔案目錄(此時可能是通過 conda 安裝的 cudatoolkit,一般直接用 conda install cudatoolkit,就是在這里搜索到 cuda 庫的),庫檔案目錄的上級目錄就作為 CUDA_HOME,
- 如果最終未能得到 CUDA_HOME,那么生成的 pytorch 將不使用 CUDA,
TensorFlow同理,但我并沒有成功修復呼叫順序的問題,那么如果conda安裝正確,且機器沒有其他版本CUDA(如/usr/local/cuda),理論上能直接用?
結論
- 如果可以用docker,可以移步TF官網docker安裝教程-最簡單方法
- 如果可以用root,可以移步博客TF安裝
- 如果conda能用,可以移步博客TF安裝-conda
0 安裝之前——檢查機器配置(非root用戶)
查詢目標配置
安裝TensorFlow環境,需要配合對應版本的CUDA、cuDNN和python,而CUDA需要配合對應版本的gcc,
我的目標是裝tf_gpu_1.6.0,從官網查到匹配的環境資訊如下:官網-TensorFlow對應CUDA
| 版本 | Python 版本 | 編譯器 | 構建工具 | cuDNN | CUDA |
|---|---|---|---|---|---|
| Tensorflow_gpu-1.6.0 | 2.7、3.3-3.6 | GCC 4.8 | Bazel 0.9.0 | 7 | 9 |
檢查機器配置
# 查看命令
cat /etc/os-release
# 或uname -a
gcc --version
nvcc -V
nvidia-smi
python --version
| 版本 | Python 版本 | 編譯器 | 構建工具 | cuDNN | CUDA |
|---|---|---|---|---|---|
| None | 3.6.1 | GCC 8.4.0 | -- | -- | 10.1 |
安裝順序
按照依賴關系,gcc -> CUDA -> cuDNN -> python -> TensorFlow
1 安裝gcc
不同的CUDA支持的gcc版本不同,現在用的服務器gcc版本比較新,實測cuda9.0在gcc8.4.0下安裝程式會失敗,所以需要降級,
首先在位置/home/[username]/, 建立目錄如下:參考博客
.
├── gcc # 新建,用于存放gcc版本
│ ├──gcc640 # 新建
│ └── gcc-6.4.0.tar.gz # 下載
└── ... # 其他檔案
1.1 下載gcc (以gcc6.4.0為例)
(方式1) 手動下載:http://ftp.gnu.org/gnu/gcc/ 后傳輸到服務器
(方式2) cmd:
wget http://ftp.gnu.org/gnu/gcc/gcc-6.4.0/gcc-6.4.0.tar.gz
1.2 configure
參考:官方gcc安裝教程
下載完成后進行解壓
cd /home/[username]/gcc
tar xzf gcc-6.4.0.tar.gz
cd gcc-6.4.0
./contrib/download_prerequisites # 運行腳本,自動安裝依賴
mkdir objdir # 在gcc-6.4.0原始碼檔案夾下,新建一個檔案夾用于編譯
cd objdir
使用configure生成 Makefile,為下一步的編譯做準備:
$PWD/../gcc-6.4.0/configure --prefix=$HOME/gcc/gcc640 --enable-checking=release --enable-languages=c,c++ --enable-threads=posix --disable-multilib
# --prefix=/usr/local/gcc6 指定安裝路徑
# --enable-languages=c,c++ 支持的編程語言
# --enable-threads=posix 使用POSIX/Unix98作為執行緒支持庫
# --disable-multilib 取消多目標庫編譯(取消32位庫編譯)
1.3 編譯
接下來編譯
make # 或者make -j8 使用8個執行緒并行編譯
可能問題1: make[3]: *** No rule to make target '../build-x86_64-pc-linux-gnu/libiberty/libiberty.a', needed by 'build/genmddeps'. Stop.
在解壓后需要在原始碼檔案夾下新建一個檔案夾,如/home/[username]/gcc/gcc-6.4.0/objdir,之后的make程序均在新建的編譯檔案夾內
** 可能問題2: ./md-unwind-support.h:65:48: error: dereferencing pointer to incomplete type 'struct ucontext'**
參考博客,原因是現在安裝版本的gcc語法不兼容:
如果你機器上已經默認安裝的是gcc8.1,現在想要使用gcc6.x,那么編譯gcc6.x原始碼程序中會出現好些錯誤,這些錯誤是因為gcc在升級程序中對頭檔案的一些結構變數的定義的更改變化沒有做向后兼容處理,或者某些語法的嚴格性要求不一樣(比較常見的是struct的定義和申明)
打開報錯指出的檔案地址
/home/[username]/gcc/gcc-6.4.0/x86_64-pc-linux-gnu/libgcc/md-unwind-support.h
修改第61行的
struct ucontext * uc_ = context->cfa;
為
struct ucontext_t * uc_ = context->cfa;

接下來繼續make
可能問題3: sanitizer_platform_limits_posix.cc:158:23: fatal error: sys/ustat.h: No such file or directory #include <sys/ustat.h>
參考博客,修改代碼檔案
vim libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc
(1)首先注釋158行#include <sys/ustat.h>
(2)將250行陳述句unsigned struct_ustat_sz = sizeof(struct ustat);注釋,修改為如下內容:
// Use pre-computed size of struct ustat to avoid <sys/ustat.h> which
// has been removed from glibc 2.28.
#if defined(__aarch64__) || defined(__s390x__) || defined (__mips64) \
|| defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) \
|| defined(__x86_64__)
#define SIZEOF_STRUCT_USTAT 32
#elif defined(__arm__) || defined(__i386__) || defined(__mips__) \
|| defined(__powerpc__) || defined(__s390__)
#define SIZEOF_STRUCT_USTAT 20
#else
#error Unknown size of struct ustat
#endif
unsigned struct_ustat_sz = SIZEOF_STRUCT_USTAT;
(3)保存后,重新make
可能問題4 :../../.././libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc:270:22: error: aggregate ‘sigaltstack handler_stack’ has incomplete type and cannot be defined
(1)打開libsanitizer/sanitizer_common/sanitizer_linux.h檔案,注釋第22行的struct sigaltstack;
(2)修改31.32行:
uptr internal_sigaltstack(const struct sigaltstack* ss,
struct sigaltstack* oss);
為
uptr internal_sigaltstack(const void* ss, void* oss);
(3)修改libsanitizer/sanitizer_common/sanitizer_linux.cc檔案549、550行
uptr internal_sigaltstack(const struct sigaltstack *ss,
struct sigaltstack *oss) {
為
uptr internal_sigaltstack(const void *ss, void *oss) {
(4)修改libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc270行
struct sigaltstack handler_stack;
為
stack_t handler_stack;
(5)修改libsanitizer/tsan/tsan_platform_linux.cc294行
__res_state *statp = (__res_state*)state;
為
struct __res_state *statp = (struct __res_state*)state;
(6)繼續make
可能問題5: ../../.././libsanitizer/sanitizer_common/sanitizer_internal_defs.h:254:72: error: size of array ‘assertion_failed__1139’ is negative
(1)修改 /gcc-6.3.0/configure檔案
(2)洗掉檔案中 target-libsanitizer \,大概在2700多行
(3)繼續make
1.4 安裝
make install
檢查包含以下目錄,即安裝成功:/home/[username]/gcc/gcc640

1.4.1 覆寫路徑
[要安裝GCC的路徑]:/home/[username]/gcc/gcc640
#路徑要在環境變數前
export PATH=[要安裝GCC的路徑]/bin:[要安裝GCC的路徑]/lib64:$PATH
export LD_LIBRARY_PATH=[要安裝GCC的路徑]/lib/:$LD_LIBRARY_PATH
最后重繪
source ~/.bashrc
1.4.2 檢查gcc設定
gcc --version
2 安裝CUDA
CUDA 下載地址:https://developer.nvidia.com/cuda-toolkit-archive
.
├── cuda # 新建,用于存放不同的cuda版本,即安裝目錄
│ ├── cuda-9.0 # 新建
│ └── tem # 新建,用于cuDNN的解壓,安裝完成后就洗掉該目錄
│ │ ├── cudnn-9.1-linux-x64-v7.1.tgz # 后續下載
│ └── cuda_9.1.85_387.26_linux.run # 后續下載
└── ... # 其他檔案
2.1 給cuda可執行權限
chmod +x cuda_9.1.85_387.26_linux.run
2.2 執行安裝
sh cuda_9.1.85_387.26_linux.run
安裝程序記錄:
-----------------
Do you accept the previously read EULA?
accept/decline/quit: accept
You are attempting to install on an unsupported configuration. Do you wish to continue?
(y)es/(n)o [ default is no ]: y
# 已有Driver API,不安裝
Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 384.81?
(y)es/(n)o/(q)uit: n
Install the CUDA 9.0 Toolkit?
(y)es/(n)o/(q)uit: y
# 非root用戶,所以安裝在自定義目錄
Enter Toolkit Location
[ default is /usr/local/cuda-9.0 ]: /home/[username]/cuda/cuda-9.0
# 非root用戶,嘗試過無法鏈接到/usr/local
Do you want to install a symbolic link at /usr/local/cuda?
(y)es/(n)o/(q)uit: n
Install the CUDA 9.0 Samples?
(y)es/(n)o/(q)uit: y
Enter CUDA Samples Location
[ default is /home/[username] ]: /home/[username]/cuda/cuda-9.0
Installing the CUDA Toolkit in /home/[username]/cuda/cuda-9.0 ...
Missing recommended library: libGLU.so
Missing recommended library: libXi.so
Missing recommended library: libXmu.so
Installing the CUDA Samples in /home/[username]/cuda/cuda-9.0 ...
Copying samples to /home/[username]/cuda/cuda-9.0/NVIDIA_CUDA-9.0_Samples now...
Finished copying samples.
2.3 卸載CUDA
參考博客
安裝程式最后已經準備好了卸載的介面,卸載程式在/[安裝目錄]/bin下,需要注意的是cuda10.0及之前的版本卸載程式名為uninstall_cuda_xx.x.pl,而cuda10.1及之后的版本卸載程式名為cuda-uninstaller,
找到之后運行卸載程式即可,這里的xx.x表示自己的cuda版本,
3 安裝cuDNN
參考博客
cudnn下載地址:https://developer.nvidia.com/rdp/cudnn-archive
3.1 解壓安裝檔案
tar -zxvf cudnn-9.1-linux-x64-v7.1.tgz
3.2 拷貝檔案到cuda
cp /home/[username]/cuda/include/cudnn.h /home/[username]/cuda/cuda-9.0/include
cp /home/[username]/cuda/lib64/libcudnn* /home/[username]/cuda/cuda-9.0/lib64
3.3 添加權限
chmod a+r /home/[username]/cuda/cuda-9.0/include/cudnn.h /home/[username]/cuda/cuda-9.0/lib64/libcudnn*
3.4 配置用戶環境變數
修改個人用戶目錄下的.bashrc檔案(用vi ~/.bashrc編輯),在檔案最后面加入以下指令并保存:
export PATH=//home/[username]/cuda/cuda-9.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/home/[username]/cuda/cuda-9.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
最后輸入命令source .bashrc 使新配置的環境變數生效
4 安裝TensorFlow
可能問題: Could not find a version that satisfies the requirement tensorflow-1.6.0 (from versions: none)
參考:https://stackoverflow.com/questions/38896424/tensorflow-not-found-using-pip
一般情況下是python版本不對應,但目前python版本是正確的,以下兩種解決方案:
(1) 把pip install替換成pip3 install --upgrade
pip3 install --upgrade TF_BINARY_URL
(2) 檢查自己的語法(事實證明是我錯寫成tensorflow-gpu-1.6.0了)
pip3 install tensorflow-gpu==1.6.0
5 檢測新環境
import tensorflow as tf
import os
os.environ['CUDA_VISIBLE_DEVICES']='4' # tensorflow默認占用機器所有卡,所以記得事先選擇
from tensorflow.python.client import device_lib
print(device_lib.list_local_devices()) # 檢查TF可用的卡
Note: TensorFlow默認會對卡從0開始重新編號
Ref:
[1] https://blog.csdn.net/wanggao_1990/article/details/120989070
[2] https://stackoverflow.com/questions/9450394/how-to-install-gcc-piece-by-piece-with-gmp-mpfr-mpc-elf-without-shared-libra
[3] https://blog.csdn.net/XCCCCZ/article/details/80958414
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/539040.html
標籤:其他
上一篇:云小課|基于華為云WAF的日志運維分析,構筑設備安全的城墻
下一篇:Linux 基礎-檔案及目錄管理
