以下內容來自於:https://zhuanlan.zhihu.com/p/91334380
在使用深度學習框架的過程中一定會經常碰到這些東西,雖然anaconda有時會幫助我們自動地解決這些設置,但是有些特殊的庫卻還是需要我們手動配置環境,但是我對標題上的這些名詞其實並不十分清楚,所以老是被網上的教程繞得雲里霧里,所以覺得有必要寫下一篇文章當做筆記供之后參考。
GPU型號含義
參考 【GPU編程系列之一】從深度學習選擇什么樣的gpu來談談gpu的硬件架構
- 顯卡: 簡單理解這個就是我們前面說的GPU,尤其指NVIDIA公司生產的GPU系列,因為后面介紹的cuda,cudnn都是NVIDIA公司針對自身的GPU獨家設計的。
- 顯卡驅動:很明顯就是字面意思,通常指NVIDIA Driver,其實它就是一個驅動軟件,而前面的顯卡就是硬件。
- gpu架構:Tesla、Fermi、Kepler、Maxwell、Pascal
- 芯片型號:GT200、GK210、GM104、GF104等
- 顯卡系列:GeForce、Quadro、Tesla
- GeForce顯卡型號:G/GS、GT、GTS、GTX
gpu架構指的是硬件的設計方式,例如流處理器簇中有多少個core、是否有L1 or L2緩存、是否有雙精度計算單元等等。每一代的架構是一種思想,如何去更好完成並行的思想
芯片就是對上述gpu架構思想的實現,例如芯片型號GT200中第二個字母代表是哪一代架構,有時會有100和200代的芯片,它們基本設計思路是跟這一代的架構一致,只是在細節上做了一些改變,例如GK210比GK110的寄存器就多一倍。有時候一張顯卡里面可能有兩張芯片,Tesla k80用了兩塊GK210芯片。這里第一代的gpu架構的命名也是Tesla,但現在基本已經沒有這種設計的卡了,下文如果提到了會用Tesla架構和Tesla系列來進行區分。
而顯卡系列在本質上並沒有什么區別,只是NVIDIA希望區分成三種選擇,GeFore用於家庭娛樂,Quadro用於工作站,而Tesla系列用於服務器。Tesla的k型號卡為了高性能科學計算而設計,比較突出的優點是雙精度浮點運算能力高並且支持ECC內存,但是雙精度能力好在深度學習訓練上並沒有什么卵用,所以Tesla系列又推出了M型號來做專門的訓練深度學習網絡的顯卡。需要注意的是Tesla系列沒有顯示輸出接口,它專注於數據計算而不是圖形顯示。
最后一個GeForce的顯卡型號是不同的硬件定制,越往后性能越好,時鍾頻率越高顯存越大,即G/GS<GT<GTS<GTX。
CUDA名稱含義
CUDA
看了很多答案,有人說CUDA就是一門編程語言,像C,C++,python 一樣,也有人說CUDA是API。CUDA英文全稱是Compute Unified Device Architecture,是顯卡廠商NVIDIA推出的運算平台。 CUDA™是一種由NVIDIA推出的通用並行計算架構,該架構使GPU能夠解決復雜的計算問題。按照官方的說法是,CUDA是一個並行計算平台和編程模型,能夠使得使用GPU進行通用計算變得簡單和優雅。
cudnn
這個其實就是一個專門為深度學習計算設計的軟件庫,里面提供了很多專門的計算函數,如卷積等。從上圖也可以看到,還有很多其他的軟件庫和中間件,包括實現c++ STL的thrust、實現gpu版本blas的cublas、實現快速傅里葉變換的cuFFT、實現稀疏矩陣運算操作的cuSparse以及實現深度學習網絡加速的cuDNN等等,具體細節可參閱GPU-Accelerated Libraries
CUDA Toolkit
參考 CUDA Toolkit
CUDA Toolkit由以下組件組成:
- Compiler: CUDA-C和CUDA-C++編譯器
NVCC
位於bin/
目錄中。它建立在NVVM
優化器之上,而NVVM
優化器本身構建在LLVM
編譯器基礎結構之上。因此開發人員可以使用nvm/
目錄下的Compiler SDK來直接針對NVVM進行開發。 - Tools: 提供一些像
profiler
,debuggers
等工具,這些工具可以從bin/
目錄中獲取 - Libraries: 下面列出的部分科學庫和實用程序庫可以在
lib/
目錄中使用(Windows上的DLL位於bin/
中),它們的接口在include/
目錄中可獲取。 - cudart: CUDA Runtime
- cudadevrt: CUDA device runtime
- cupti: CUDA profiling tools interface
- nvml: NVIDIA management library
- nvrtc: CUDA runtime compilation
- cublas: BLAS (Basic Linear Algebra Subprograms,基礎線性代數程序集)
- cublas_device: BLAS kernel interface
- ...
- CUDA Samples: 演示如何使用各種CUDA和library API的代碼示例。可在Linux和Mac上的
samples/
目錄中獲得,Windows上的路徑是C:\ProgramData\NVIDIA Corporation\CUDA Samples
中。在Linux和Mac上,samples/
目錄是只讀的,如果要對它們進行修改,則必須將這些示例復制到另一個位置。 - CUDA Driver: 運行CUDA應用程序需要系統至少有一個具有CUDA功能的GPU和與CUDA工具包兼容的驅動程序。每個版本的CUDA工具包都對應一個最低版本的CUDA Driver,也就是說如果你安裝的CUDA Driver版本比官方推薦的還低,那么很可能會無法正常運行。CUDA Driver是向后兼容的,這意味着根據CUDA的特定版本編譯的應用程序將繼續在后續發布的Driver上也能繼續工作。通常為了方便,在安裝CUDA Toolkit的時候會默認安裝CUDA Driver。在開發階段可以選擇默認安裝Driver,但是對於像Tesla GPU這樣的商用情況時,建議在官方安裝最新版本的Driver。 目前(2019年10月)的CUDA Toolkit和CUDA Driver版本的對應情況如下:
nvcc
&nvidia-smi
nvcc
這個在前面已經介紹了,nvcc
其實就是CUDA的編譯器,可以從CUDA Toolkit的/bin
目錄中獲取,類似於gcc
就是c語言的編譯器。由於程序是要經過編譯器編程成可執行的二進制文件,而cuda程序有兩種代碼,一種是運行在cpu上的host代碼,一種是運行在gpu上的device代碼,所以nvcc
編譯器要保證兩部分代碼能夠編譯成二進制文件在不同的機器上執行。nvcc涉及到的文件后綴及相關意義如下表
nvidia-smi
nvidia-smi
全程是NVIDIA System Management Interface ,它是一個基於前面介紹過的NVIDIA Management Library(NVML)
構建的命令行實用工具,旨在幫助管理和監控NVIDIA GPU設備。
nvcc
和nvidia-smi
顯示的CUDA版本不同?
在我們實驗室的服務器上nvcc --version
顯示的結果如下:
nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2018 NVIDIA Corporation Built on Tue_Jun_12_23:07:04_CDT_2018 Cuda compilation tools, release 9.2, V9.2.148
而nvidia-smi
顯示結果如下:
+-----------------------------------------------------------------------------+ | NVIDIA-SMI 410.104 Driver Version: 410.104 CUDA Version: 10.0 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 Tesla V100-PCIE... On | 00000000:01:00.0 Off | Off | | N/A 28C P0 26W / 250W | 0MiB / 16130MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 1 Tesla P100-PCIE... On | 00000000:02:00.0 Off | Off | | N/A 24C P0 30W / 250W | 0MiB / 16280MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
可以看到nvcc
的CUDA 版本是9.2,而nvidia-smi
的CUDA版本是10.0。很奇怪的是有時候絕大多數情況代碼也能整成跑起來,stackoverflow上的一個解釋如下:
CUDA有兩個主要的API:runtime(運行時) API和driver 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。
runtime和driver API區別
下圖很清楚的展示前面提到的各種概念之間的關系,其中runtime和driver API在很多情況非常相似,也就是說用起來的效果是等價的,但是你不能混合使用這兩個API,因為二者是互斥的。也就是說在開發過程中,你只能選擇其中一種API。簡單理解二者的區別就是:runtime是更高級的封裝,開發人員用起來更方便,而driver API更接近底層,速度可能會更快。
兩種API詳細的區別如下:
- 復雜性
- runtime API通過提供隱式初始化、上下文管理和模塊管理來簡化設備代碼管理。這使得代碼更簡單,但也缺乏驅動程序API所具有的控制級別。
- 相比之下,driver API提供了更細粒度的控制,特別是在上下文和模塊加載方面。實現內核啟動要復雜得多,因為執行配置和內核參數必須用顯式函數調用指定。
- 控制
- 對於runtime API,其在運行時,所有內核都在初始化期間自動加載,並在程序運行期間保持加載狀態。
- 而使用driver API,可以只加載當前需要的模塊,甚至動態地重新加載模塊。driver API也是語言獨立的,因為它只處理
cubin
對象。 - 上下文管理 上下文管理可以通過driver API完成,但是在runtime API中不公開。相反,runtime API自己決定為線程使用哪個上下文:
- 如果一個上下文通過driver API成為調用線程的當前上下文,runtime將使用它,
- 如果沒有這樣的上下文,它將使用“主上下文(primary context)”。
主上下文會根據需要創建,每個設備每個進程一個上下文,並進行引用計數,然后在沒有更多的引用時銷毀它們。在一個進程中,所有runtime API的用戶都將共享主上下文,除非上下文已成為每個線程的當前上下文。runtime使用的上下文,即當前上下文或主上下文,可以用cudaDeviceSynchronize()
同步,也可以用cudaDeviceReset()
銷毀。 但是,將runtime API與主上下文一起使用會有tradeoff。例如,對於那些需要給較大的軟件包寫插件的開發者來說者會帶來不少麻煩,因為如果所有的插件都在同一個進程中運行,它們將共享一個上下文,但可能無法相互通信。也就是說,如果其中一個在完成所有CUDA工作后調用cudaDeviceReset()
,其他插件將失敗,因為它們使用的上下文在它們不知情的情況下被破壞。為了避免這個問題,CUDA clients可以使用driver API來創建和設置當前上下文,然后使用runtime API來處理它。但是,上下文可能會消耗大量的資源,比如設備內存、額外的主機線程和設備上上下文切換的性能成本。當將driver API與基於runtime API(如cuBLAS或cuFFT)構建的庫一起使用時,這種runtime-driver上下文共享非常重要。
Linux中PATH、 LIBRARY_PATH、 LD_LIBRARY_PATH的區別
參考 Linux中PATH、 LIBRARY_PATH、 LD_LIBRARY_PATH的區別
PATH
PATH是可執行文件路徑,是三個中我們最常接觸到的,因為我們命令行中的每句能運行的命令,如ls、top、ps等,都是系統通過PATH找到了這個命令執行文件的所在位置,再run這個命令(可執行文件)。 比如說,在用戶的目錄~/mycode/
下有一個bin文件夾,里面放了有可執行的二進制文件、shell腳本等。如果想要在任意目錄下都能運行上述bin文件夾的可執行文件,那么只需要把這個bin的路徑添加到PATH即可,方法如下:
# vim ~/.bashrc PATH=$PATH:~/mycode/bin
LIBRARY_PATH和LD_LIBRARY_PATH
這兩個路徑可以放在一起討論,
LIBRARY_PATH
是程序編譯期間查找動態鏈接庫時指定查找共享庫的路徑LD_LIBRARY_PATH
是程序加載運行期間查找動態鏈接庫時指定除了系統默認路徑之外的其他路徑
兩者的共同點是庫,庫是這兩個路徑和PATH路徑的區別,PATH是可執行文件。
兩者的差異點是使用時間不一樣。一個是編譯期,對應的是開發階段,如gcc編譯;一個是加載運行期,對應的是程序已交付的使用階段。
配置方法也是類似:
export LD_LIBRARY_PATH=LD_LIBRARY_PATH:XXXX
多版本CUDA切換
參考 安裝多版本cuda,多版本之間切換
基於前面幾個小節的介紹,現在再來介紹如何管理多版本CUDA就會好懂很多了。
cuda 的下載與安裝方法選擇
到 CUDA Toolkit Download 下載所需版本,以 cuda_9.0.176_384.81_linux.run為例:
建議選擇使用 .run
文件安裝,因為使用 .deb
可能會將已經安裝的較新的顯卡驅動替換。
cuda 安裝
進入到放置 cuda_9.0.176_384.81_linux.run
的目錄:
sudo chmod +x cuda_9.0.176_384.81_linux.run # 為 cuda_9.0.176_384.81_linux.run 添加可執行權限 ./cuda_9.0.176_384.81_linux.run # 安裝 cuda_9.0.176_384.81_linux.run
在安裝過程中截取其中比較重要的幾個選擇:
Do you accept the previously read EULA? accept/decline/quit: accept Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 384.81? (y)es/(n)o/(q)uit: n # 如果在這之前已經安裝好更高版本的顯卡驅動就不需要再重復安裝,如果需要重復安裝就選擇 yes,此外還需要關閉圖形界面。 Install the CUDA 9.0 Toolkit? (y)es/(n)o/(q)uit: y Enter Toolkit Location [ default is /usr/local/cuda-9.0 ]: # 一般選擇默認即可,也可以選擇安裝在其他目錄,在需要用的時候指向該目錄或者使用軟連接 link 到 /usr/local/cuda。 /usr/local/cuda-9.0 is not writable. Do you wish to run the installation with 'sudo'? (y)es/(n)o: y Please enter your password: Do you want to install a symbolic link at /usr/local/cuda? # 是否將安裝目錄通過軟連接的方式 link 到 /usr/local/cuda,yes or no 都可以,取決於你是否使用 /usr/local/cuda 為默認的 cuda 目錄。 (y)es/(n)o/(q)uit: n Install the CUDA 9.0 Samples? (y)es/(n)o/(q)uit: n
前面選擇的一些匯總:
Driver: Not Selected
Toolkit: Installed in /usr/local/cuda-9.0
Samples: Not Selected
Please make sure that
- PATH includes /usr/local/cuda-9.0/bin
- LD_LIBRARY_PATH includes /usr/local/cuda-9.0/lib64, or, add /usr/local/cuda-9.0/lib64 to /etc/ld.so.conf and run ldconfig as root
To uninstall the CUDA Toolkit, run the uninstall script in /usr/local/cuda-9.0/bin
Please see CUDA_Installation_Guide_Linux.pdf in /usr/local/cuda-9.0/doc/pdf for detailed information on setting up CUDA. ***WARNING: Incomplete installation! This installation did not install the CUDA Driver. A driver of version at least 384.00 is required for CUDA 9.0 functionality to work. To install the driver using this installer, run the following command, replacing <CudaInstaller> with the name of this run file: sudo <CudaInstaller>.run -silent -driver
安裝完成后可以在 /usr/local 目錄下看到:
cuda-8.0 # 筆者之前安裝的cuda-8.0 cuda-9.0 # 剛剛安裝的cuda-9.0 cuda # cuda-8.0 的軟連接
多個 cuda 版本之間進行切換
將~/.bashrc
或 ~/.zshrc
下與cuda相關的路徑都改為 /usr/local/cuda/
而不使用 /usr/local/cuda-8.0/
或/usr/local/cuda-9.0/
。
#在切換cuda版本時 rm -rf /usr/local/cuda#刪除之前創建的軟鏈接 sudo ln -s /usr/local/cuda-8.0/ /usr/local/cuda/ nvcc --version #查看當前 cuda 版本 nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2016 NVIDIA Corporation Built on Mon_Jan_23_12:24:11_CST_2017 Cuda compilation tools, release 8.0, V8.0.62 #cuda8.0 切換到 cuda9.0 rm -rf /usr/local/cuda sudo ln -s /usr/local/cuda-9.0/ /usr/local/cuda/ nvcc --version
Conda安裝的CUDA Toolkit和NVIDIA的CUDA Toolkit到底什么區別?
上面說了那么多可能看得雲里霧里,下面做一個小的總結(參考下文)。
Nvidia 官方提供的 CUDA Toolkit 是一個完整的工具安裝包,其中提供了 Nvidia 驅動程序、開發 CUDA 程序相關的開發工具包等可供安裝的選項。使用 Nvidia 官網提供的 CUDA Toolkit 可以安裝開發 CUDA 程序所需的工具,包括 CUDA 程序的編譯器、IDE、調試器等,CUDA 程序所對應的各式庫文件以及它們的頭文件。
但對於 Pytorch 之類的深度學習框架而言,其在大多數需要使用 GPU 的情況中只需要使用 CUDA 的動態鏈接庫支持程序的運行( Pytorch 本身與 CUDA 相關的部分是提前編譯好的 ),就像常見的可執行程序一樣,不需要重新進行編譯過程,只需要其所依賴的動態鏈接庫存在即可正常運行。
Anaconda 在安裝 Pytorch 等會使用到 CUDA 的框架時,會自動為用戶安裝 cudatoolkit,其主要包含應用程序在使用 CUDA 相關的功能時所依賴的動態鏈接庫,不會安裝驅動程序。在安裝了 cudatoolkit 后,只要系統上存在與當前的 cudatoolkit 所兼容的 Nvidia 驅動,則已經編譯好的 CUDA 相關的程序就可以直接運行,而不需要安裝完整的 Nvidia 官方提供的 CUDA Toolkit .
總的來說,你可以把Anaconda安裝的 Toolkit 看成是一個組裝好的汽車,型號是10.0,恰巧你又安裝了10.0版本的NVIDIA的CUDA驅動程序,那么你就有了10.0的鑰匙,那么你就可以直接開豪車了。 反之,如果你只有9.0的鑰匙,那你此時有兩個解決辦法,一是用Anaconda安裝9.0版本的Pytorch,另一個是另外配一把10.0的鑰匙。如何切換不同鑰匙的方法在上文已經介紹了。