顯卡,顯卡驅動,nvcc, cuda driver,cudatoolkit,cudnn到底是什么?


在使用深度學習框架的過程中一定會經常碰到這些東西,雖然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進行通用計算變得簡單和優雅

image.png

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版本的對應情況如下:
CUDA Toolkit Linux x86_64 Driver Version Windows x86_64 Driver Version
CUDA 10.1 (10.1.105 general release, and updates) >= 418.39 >= 418.96
CUDA 10.0.130 >= 410.48 >= 411.31
CUDA 9.2 (9.2.148 Update 1) >= 396.37 >= 398.26
CUDA 9.2 (9.2.88) >= 396.26 >= 397.44
CUDA 9.1 (9.1.85) >= 390.46 >= 391.29
CUDA 9.0 (9.0.76) >= 384.81 >= 385.54
CUDA 8.0 (8.0.61 GA2) >= 375.26 >= 376.51
CUDA 8.0 (8.0.44) >= 367.48 >= 369.30
CUDA 7.5 (7.5.16) >= 352.31 >= 353.66
CUDA 7.0 (7.0.28) >= 346.46 >= 347.62

nvcc&nvidia-smi

nvcc

這個在前面已經介紹了,nvcc其實就是CUDA的編譯器,可以從CUDA Toolkit的/bin目錄中獲取,類似於gcc就是c語言的編譯器。由於程序是要經過編譯器編程成可執行的二進制文件,而cuda程序有兩種代碼,一種是運行在cpu上的host代碼,一種是運行在gpu上的device代碼,所以nvcc編譯器要保證兩部分代碼能夠編譯成二進制文件在不同的機器上執行。nvcc涉及到的文件后綴及相關意義如下表

文件后綴 意義
.cu cuda源文件,包括host和device代碼
.cup 經過預處理的cuda源文件,編譯選項--preprocess/-E
.c c源文件
.cc/.cxx/.cpp c++源文件
.gpu gpu中間文件,編譯選項--gpu
.ptx 類似匯編代碼,編譯選項--ptx
.o/.obj 目標文件,編譯選項--compile/-c
.a/.lib 庫文件,編譯選項--lib/-lib
.res 資源文件
.so 共享目標文件,編譯選項--shared/-shared
.cubin cuda的二進制文件,編譯選項-cubin

nvidia-smi

nvidia-smi全程是NVIDIA System Management Interface ,它是一個基於前面介紹過的NVIDIA Management Library(NVML)構建的命令行實用工具,旨在幫助管理和監控NVIDIA GPU設備。

nvccnvidia-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(運行時) APIdriver 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為例:

image.png

建議選擇使用 .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

這篇文章花了我一天的時間來整理,所以如果覺得有幫助給個贊可好。



微信公眾號:AutoML機器學習
MARSGGBO原創
如有意合作或學術討論歡迎私戳聯系~
郵箱:marsggbo@foxmail.com

2019-11-11 10:01:03




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM