CUDA环境详解
CUDA環境詳解
本文主要介紹 CUDA 環境,這一堆東西網上有很多博客介紹過了,我再來一篇:),參考前輩們的文章,看能不能寫的更清楚一點。讀后仍有問題,歡迎留言交流。
CUDA APIs
CUDA是由NVIDIA推出的通用并行計算架構,通過一些CUDA庫提供了一系列API供應用程序調用。開發者可調用這些API充分利用GPU來處理圖像,視頻解碼等。
CUDA 的 API 其實是可以分層次來理解的,這也造成了有時會出現 nvcc -V 顯示的 CUDA 版本和 nvidia-smi 顯示的 CUDA 版本不一致的情況,其實這就是由于它們根本就是不同層次的 API,因此并不一定是一起安裝的,也就不一定是同一個版本的。
CUDA API體系包括:CUDA函數庫(CUDA Libraries),CUDA運行時API(CUDA Runtime API),CUDA驅動API(CUDA Driver API),結構圖如下:
圖1:CUDA API體系結構,圖源:[1]CUDA Driver API
GPU設備的抽象層,通過提供一系列接口來操作GPU設備,性能最好,但編程難度高,一般不會使用該方式開發應用程序。
用于支持driver API的必要文件(如libcuda.so)是由GPU driver installer安裝的。 我么你常用的 nvidia-smi就屬于這一類API。
CUDA Runtime API
對CUDA Driver API進行了一定的封裝,調用該類API可簡化編程過程,降低開發難度。
用于支持runtime API的必要文件(如libcudart.so以及nvcc)是由CUDA Toolkit installer安裝的。
CUDA Toolkit Installer:有時可能會集成了GPU driver Installer。nvcc是與CUDA Toolkit一起安裝的CUDA compiler-driver tool,即 CUDA 的編譯器,它只知道它自身構建時的 CUDA runtime版本。它不知道安裝了什么版本的GPU driver,甚至不知道是否安裝了GPU driver。
CUDA Libraries
是對CUDA Runtime API更高一層的封裝,通常是一些成熟的高效函數庫,開發者也可以自己封裝一些函數庫便于使用。
比如常見的 cuFFT、cuBLAS 庫。
關系
應用程序可調用CUDA Libraries或者CUDA Runtime API來實現功能,當調用CUDA Libraries時,CUDA Libraries會調用相應的CUDA Runtime API,CUDA Runtime API再調用CUDA Driver API,CUDA Driver API再操作GPU設備。
cudatoolkit
幾個概念辨析
- CUDA:為“GPU通用計算”構建的運算平臺。
- cuDNN:為深度學習計算設計的軟件庫。
- CUDA Toolkit (Nvidia): CUDA完整的工具安裝包,其中提供了 Nvidia 驅動程序、開發 CUDA 程序相關的開發工具包等可供安裝的選項。包括 CUDA 程序的編譯器、IDE、調試器等,CUDA 程序所對應的各式庫文件以及它們的頭文件。
- CUDA Toolkit (Pytorch): CUDA不完整的工具安裝包,其主要包含在使用 CUDA 相關的功能時所依賴的動態鏈接庫。不會安裝驅動程序。
- NVCC 是CUDA的編譯器,只是 CUDA Toolkit 中的一部分
注:CUDA Toolkit 完整和不完整的區別:在安裝了CUDA Toolkit (Pytorch)后,只要系統上存在與當前的 cudatoolkit 所兼容的 Nvidia 驅動,則已經編譯好的 CUDA 相關的程序就可以直接運行,不需要重新進行編譯過程。如需要為 Pytorch 框架添加 CUDA 相關的拓展時(Custom C++ and CUDA Extensions),需要對編寫的 CUDA 相關的程序進行編譯等操作,則需安裝完整的 Nvidia 官方提供的 CUDA Toolkit。
完整版cudatoolkit內容
一般的結構中,include 包含頭文件,bin 包含可執行文件,lib 包含程序實現文件編譯生成的library,src包含源代碼,doc或help包含文檔,samples包含例子。
- Compiler:NVCC
- Tools:分析器profiler、調試器debuggers等
- Libraries:科學庫和實用程序庫
- CUDA Samples:CUDA和library API的代碼示例
- CUDA Driver:驅動,需要與“有CUDA功能的GPU”和“CUDA”都兼容。CUDA工具包都對應一個最低版本的CUDA Driver,CUDA Driver向后兼容。
conda下的cudatoolkit
通過 conda 安裝 cudatoolkit 包含的庫文件在 ~/anaconda3/lib 中,或者在 ~/anaconda3/pkgs/cudatoolkit-xxx/lib 中查看,grep 一下 libcu、libnpp、libnv 這幾個名字查看即可,當然這樣 grep 出來的也不一定確實 cudatoolkit 的文件,可能有 libcurl 之類的,只是初步過濾。
ls ~/anaconda3/lib/ | egrep 'libcu|libnpp|libnv' ls ~/anaconda3/pkgs/cudatoolkit-11.0.221-h6bb024c_0/lib/ | egrep 'libcu|libnpp|libnv' # 這里的11.0.221-h6bb024c_0z是筆者的版本。大家的可能不同,請自行查看確認conda 的 cudatoolkit只包含pytorch或其他框架( tensorflow、xgboost、Cupy)會使用到的so庫文件。
本機CUDA多版本管理
修改軟連接
我們安裝的不同版本的 CUDA Runtime API 一般都會在 /usr/local 目錄下。
我們可以通過:
ls -l /usr/local | grep cuda來查看自己的機器上有多少個cuda版本,通常不帶版本號的 cuda 會是其他帶版本號的cuda-x.x的軟鏈接。即像下面這樣:
lrwxrwxrwx 1 root root 21 12月 10 2020 cuda -> /usr/local/cuda-11.1/而我們只要把我們使用cuda時都指向這個軟鏈接 /usr/local/cuda,并在需要切換版本時切換這個軟鏈接的指向即可。
sudo rm -rf cuda sudo ln -s /usr/local/cuda-9.0 /usr/local/cuda修改環境變量
注意此時如果nvcc -V的輸出還是更改之前的CUDA版本的話, 可能是環境變量中直接指定了 CUDA 版本路徑,比如在 ~/.bashrc 中有類似以下的語句:
export PATH=/usr/local/cuda-11.1/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda-11.1/lib64:$LD_LIBRARY_PATH此時我們要修改環境變量為(在命令行中執行僅當前終端生效,修改 ~/.bashrc 永久生效):
export PATH=/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH就可以愉快地用指向 /usr/local/cuda 的軟鏈接來控制本機的 CUDA 版本了。
附:幾個環境變量的含義
PATH
PATH是可執行文件路徑,是三個中我們最常接觸到的,因為我們命令行中的每句能運行的命令,如ls、top、ps等,都是系統通過PATH找到了這個命令執行文件的所在位置,再run這個命令(可執行文件)。 比如說,在用戶的目錄~/mycode/下有一個bin文件夾,里面放了有可執行的二進制文件、shell腳本等。如果想要在任意目錄下都能運行上述bin文件夾的可執行文件,那么只需要把這個bin的路徑添加到PATH即可,方法如下:
# vim ~/.bashrc PATH=~/mycode/bin:$PATHLIBRARY_PATH和LD_LIBRARY_PATH
這兩個路徑可以放在一起討論,
- LIBRARY_PATH是程序編譯期間查找動態鏈接庫時指定查找共享庫的路徑
- LD_LIBRARY_PATH是程序加載運行期間查找動態鏈接庫時指定除了系統默認路徑之外的其他路徑
兩者的共同點是庫,庫是這兩個路徑和PATH路徑的區別,PATH是可執行文件。
兩者的差異點是使用時間不一樣。一個是編譯期,對應的是開發階段,如gcc編譯;一個是加載運行期,對應的是程序已交付的使用階段。
配置方法也是類似:
export LD_LIBRARY_PATH=XXXX:$LD_LIBRARY_PATHPytorch CUDA版本相關的幾個常用的變量
我們通常考察 Pytorch 中的以下幾個變量來確定當前 Pytorch 的 CUDA 信息:
- torch.cuda.is_available(),CUDA 是否可用。
- torch.version.cuda,CUDA 版本。
- torch.utils.cpp_extension.CUDA_HOME, CUDA 路徑 CUDA_HOME。
可以通過下面這一句來在命令行中查看上述三個變量信息:
python -c "import torch; from torch.utils.cpp_extension import CUDA_HOME; print(torch.cuda.is_available(), torch.version.cuda, CUDA_HOME)"Pytorch用的到底是哪個版本的CUDA?
其實就是看 CUDA_HOME 環境變量到底被指定為什么。
Pytorch 搜索 CUDA_HOME 的順序如下:
顯式指定的環境變量 CUDA_HOME
即如:
export CUDA_HOME=/usr/local/cuda11.5即直接指定 /usr/local/cuda11.5 路徑下的 CUDA 為使用的 CUDA。
默認搜索的路徑 /usr/local/cuda
我們之前也提到過本機 CUDA 多版本管理通常是通過改變上述路徑的軟鏈接來實現,這也是 Pytorch 一個默認會搜索的路徑。
nvcc 的所在目錄
即 which nvcc 的上級目錄,之前提到過,nvcc 是 CUDA 的編譯器,但是,他對于 Pytorch 并不是必須的,即可能 nvcc 并不存在,但是 Pytorch 還是可以正常通過 cudatoolkit 來調用 GPU,即下一條。
cudatoolkit
如果上述都不存在,則 torch.utils.cpp_extension.CUDA_HOME 會被設置為 None。然后 Pytorch 會使用 conda 安裝的 cudatoolkit,其路徑為cudart 庫文件目錄的上級目錄(此時可能是通過 conda 安裝的 cudatoolkit,一般直接用 conda install cudatoolkit,就是在這里搜索到 cuda 庫的)。
Ref:
[1]:NVIDIA Docker CUDA容器化原理分析
[2]:怎么在docker中使用nvidia顯卡
[3]:[docker gpu報錯Error response from daemon: could not select device driver ““ with capabilities: [[gpu]]](https://blog.csdn.net/weixin_44966641/article/details/123760614)
總結
- 上一篇: 工行跨行转账多久可以到
- 下一篇: vimrc配置文件