動(dòng)安裝全流程及常見故障排查)
1. 項(xiàng)目背景與環(huán)境預(yù)檢搞GPU服務(wù)器的朋友肯定都有體會(huì)CentOS 7系統(tǒng)穩(wěn)是穩(wěn)但裝驅(qū)動(dòng)這件事稍不留神就黑屏、卡死、循環(huán)登錄甚至內(nèi)核直接崩潰。我給一臺(tái)某高校實(shí)驗(yàn)室的深度學(xué)習(xí)服務(wù)器裝機(jī)時(shí)就折騰了整整一下午這里把完整流程和踩過的坑都記錄下來。先說清楚這臺(tái)設(shè)備的配置CPU是Intel至強(qiáng)系列顯卡是某型號(hào)的NVIDIA專業(yè)卡系統(tǒng)是CentOS 7.9內(nèi)核版本3.10.0機(jī)器上有兩塊機(jī)械硬盤一塊裝系統(tǒng)一塊純做數(shù)據(jù)盤內(nèi)存64G。整個(gè)流程的目標(biāo)很簡(jiǎn)單裝上NVIDIA官方驅(qū)動(dòng)讓nvidia-smi能正常輸出GPU計(jì)算能跑起來后續(xù)跑深度學(xué)習(xí)框架不報(bào)錯(cuò)。動(dòng)手之前這四件事必須先做少一件都容易翻車。1.1 確認(rèn)顯卡型號(hào)和系統(tǒng)環(huán)境這一步很多人會(huì)跳過但偏偏最容易踩坑。驅(qū)動(dòng)不是越新越好顯卡型號(hào)不同、顯存大小不同對(duì)應(yīng)能裝的驅(qū)動(dòng)版本差異很大。我遇到過有人拿著老掉牙的卡硬裝最新驅(qū)動(dòng)結(jié)果編譯直接報(bào)錯(cuò)報(bào)錯(cuò)信息看著像內(nèi)核頭文件缺失其實(shí)是驅(qū)動(dòng)壓根不支持老架構(gòu)。lspci | grep -i nvidia cat /etc/redhat-release uname -rlspci顯示的是硬件層面的顯卡型號(hào)比如NVIDIA GeForce GTX 1080或者NVIDIA Tesla V100。這一步確認(rèn)了實(shí)際硬件后去NVIDIA官網(wǎng)查對(duì)應(yīng)驅(qū)動(dòng)版本的適配表。這里有個(gè)原則優(yōu)先選擇NVIDIA官網(wǎng)提供的對(duì)應(yīng)顯卡型號(hào)的長(zhǎng)期支持版本Long Lived Branch不要追新。實(shí)驗(yàn)室那臺(tái)服務(wù)器最終選的驅(qū)動(dòng)版本是530.41.03適配Tesla系列和部分GeForce系列CUDA 12.2配套也穩(wěn)定。系統(tǒng)環(huán)境主要看內(nèi)核版本CentOS 7默認(rèn)是3.10.0如果自己編譯過內(nèi)核或者升級(jí)過版本會(huì)更高。NVIDIA驅(qū)動(dòng)需要對(duì)應(yīng)版本的內(nèi)核頭文件和源碼包這兩個(gè)東西必須和當(dāng)前內(nèi)核完全匹配。我見過有人裝完驅(qū)動(dòng)后重啟系統(tǒng)起不來排查半天發(fā)現(xiàn)是內(nèi)核頭文件版本不對(duì)驅(qū)動(dòng)模塊編譯出來加載不上。1.2 確認(rèn)nouveau開源驅(qū)動(dòng)占用情況CentOS 7默認(rèn)帶著開源的nouveau驅(qū)動(dòng)這個(gè)驅(qū)動(dòng)和NVIDIA官方驅(qū)動(dòng)沖突一起加載必出問題。裝官方驅(qū)動(dòng)前必須把nouveau徹底禁用掉否則你在nvidia-installer時(shí)它會(huì)提示nouveau正在使用然后直接退出。檢查nouveau的狀態(tài)lsmod | grep nouveau只要輸出里有nouveau字樣就說明它已經(jīng)加載到內(nèi)核里了。禁用它的做法是在/etc/modprobe.d/下新建一個(gè)配置文件寫入黑名單設(shè)置然后重建initramfs讓系統(tǒng)啟動(dòng)時(shí)不再加載nouveau模塊。禁用操作本身不難但要注意改完initramfs之后必須重啟系統(tǒng)而且重啟前要確認(rèn)配置寫對(duì)了。我見過有人改了配置沒重啟就急著裝驅(qū)動(dòng)裝到一半卡死然后一頭霧水。另一個(gè)坑是某些系統(tǒng)鏡像預(yù)裝了圖形界面拿nouveau做桌面顯示的這種機(jī)器要進(jìn)入純字符模式再操作否則圖形界面會(huì)占用GPU設(shè)備驅(qū)動(dòng)安裝時(shí)訪問/dev/nvidia0失敗。1.3 確認(rèn)內(nèi)核頭文件和gcc等編譯環(huán)境NVIDIA官方驅(qū)動(dòng)的run包是現(xiàn)場(chǎng)編譯內(nèi)核模塊的需要內(nèi)核頭文件包和gcc、make、glibc-devel等基礎(chǔ)工具。缺少任何一個(gè)裝驅(qū)動(dòng)時(shí)都會(huì)在編譯階段報(bào)錯(cuò)而編譯報(bào)錯(cuò)的類型很多看著嚇人但原因往往就是環(huán)境不全。yum install -y gcc make kernel-devel-$(uname -r) epel-release上面這條命令的關(guān)鍵在于kernel-devel-$(uname -r)的動(dòng)態(tài)匹配。很多人分不清kernel-headers和kernel-devel的區(qū)別前者只提供頭文件后者才包含完整的聲名和部分源碼連接是鏈接到/usr/src/kernels/目錄下的內(nèi)容NVIDIA驅(qū)動(dòng)編譯時(shí)需要的是kernel-devel。如果裝完后執(zhí)行l(wèi)s /usr/src/kernels/沒看到對(duì)應(yīng)版本目錄那就是裝錯(cuò)了。個(gè)別情況下yum源里找不到匹配內(nèi)核版本的kernel-devel這時(shí)候要么換一個(gè)可用的源要么手動(dòng)去某軟件倉庫下載對(duì)應(yīng)RPM包安裝。1.4 規(guī)劃驅(qū)動(dòng)安裝方式驅(qū)動(dòng)安裝主要有四種方式不同方式適配不同場(chǎng)景我這里簡(jiǎn)單對(duì)比一下后續(xù)章節(jié)會(huì)詳細(xì)講其中兩條路線安裝方式適用場(chǎng)景優(yōu)點(diǎn)缺點(diǎn)官方run包絕大多數(shù)生產(chǎn)環(huán)境、服務(wù)器最穩(wěn)定、可選參數(shù)多、可控性強(qiáng)需要編譯環(huán)境、操作繁瑣ELRepo kmod-nvidiaCentOS/RHEL官方社區(qū)源安裝快、自動(dòng)更新版本滯后、某些特定卡不支持CUDA toolkit捆綁驅(qū)動(dòng)跑深度學(xué)習(xí)框架一次搞定CUDA版本綁定后續(xù)升級(jí)驅(qū)動(dòng)麻煩系統(tǒng)自帶gnome軟件有圖形桌面的場(chǎng)景圖形化簡(jiǎn)單兼容性差服務(wù)器一般不碰我最終選了官方run包方式原因很簡(jiǎn)單這臺(tái)機(jī)器是給深度學(xué)習(xí)用的CUDA版本要自己控制驅(qū)動(dòng)版本也要和CUDA做匹配run包方式可以精準(zhǔn)控制這些變量。ELRepo雖然簡(jiǎn)單快速但它的驅(qū)動(dòng)版本通常滯后幾個(gè)月新卡支持往往跟不上CUDA toolkit捆綁的驅(qū)動(dòng)則存在互相覆蓋的問題后續(xù)想單獨(dú)換驅(qū)動(dòng)版本時(shí)會(huì)比較繞。2. 驅(qū)動(dòng)安裝方案的完整流程CentOS 7下裝NVIDIA驅(qū)動(dòng)選官方run包是相對(duì)最靠譜的一條路。這里我把每一步操作和背后的邏輯都拆開講清楚。2.1 禁用nouveau驅(qū)動(dòng)的完整操作先創(chuàng)建一個(gè)黑名單配置文件vim /etc/modprobe.d/blacklist-nouveau.conf寫入以下內(nèi)容blacklist nouveau options nouveau modeset0第一行告訴內(nèi)核不要加載nouveau第二行關(guān)閉它的模式設(shè)置功能。寫完保存后需要重新生成initramfs鏡像mv /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak dracut /boot/initramfs-$(uname -r).img $(uname -r)注意這里不是直接用dracut -f強(qiáng)制覆蓋而是先備份原文件這樣萬一新生成的initramfs有問題還能回滾。重新生成鏡像的過程大概十幾秒輸出會(huì)顯示/boot/initramfs-3.10.0-1160.99.1.el7.x86_64.img之類的字樣后面跟一串模塊列表看到nouveau出現(xiàn)在其中也不用慌黑名單配置早就寫好了它不會(huì)再被加載。改完后重啟系統(tǒng)重啟后再次執(zhí)行l(wèi)smod | grep nouveau這條命令不輸出任何內(nèi)容就對(duì)了。如果還有輸出大概率是黑名單配置文件沒生效檢查一下文件權(quán)限和路徑拼寫。順便說一下有時(shí)候/etc/modprobe.d/里已經(jīng)有別的文件寫入了nouveau相關(guān)內(nèi)容比如某些云鏡像生成的blacklist.conf這種需要仔細(xì)檢查不要一個(gè)文件沒生效就急著繼續(xù)。2.2 進(jìn)入純命令行模式安裝RPM系發(fā)行版在安裝NVIDIA驅(qū)動(dòng)時(shí)通常建議停掉圖形界面因?yàn)閄 Server會(huì)占用GPU設(shè)備。服務(wù)器有圖形界面的情況雖然不多見但還是提一下CentOS 7如果裝了GNOME桌面要先把默認(rèn)運(yùn)行級(jí)別切到多用戶模式。systemctl get-default systemctl set-default multi-user.target如果是臨時(shí)切換可以用systemctl isolate multi-user.target或者直接init 3進(jìn)入字符界面。切換之前注意保存工作因?yàn)閳D形界面會(huì)直接殺掉。還有一種情況是SSH遠(yuǎn)程連接安裝根本不需要圖形界面直接按命令行操作就行但如果機(jī)器上裝了X Server且正在運(yùn)行建議還是先停掉。跑安裝腳本前需要把驅(qū)動(dòng)run包上傳到服務(wù)器比如放到/tmp目錄下然后加上執(zhí)行權(quán)限chmod x NVIDIA-Linux-x86_64-530.41.03.run ./NVIDIA-Linux-x86_64-530.41.03.run --silent --no-opengl-files--no-opengl-files這個(gè)參數(shù)很關(guān)鍵OpenGL文件會(huì)和系統(tǒng)已有的GL庫沖突有時(shí)會(huì)導(dǎo)致圖形界面起不來。如果純計(jì)算服務(wù)器不需要桌面顯示直接帶上這個(gè)參數(shù)最保險(xiǎn)。2.3 處理Secure Boot和內(nèi)核模塊簽名問題現(xiàn)在的服務(wù)器主板基本都默認(rèn)開啟Secure Boot這會(huì)給NVIDIA驅(qū)動(dòng)安裝帶來額外麻煩。CentOS 7內(nèi)核如果是在Secure Boot模式下啟動(dòng)的加載第三方內(nèi)核模塊時(shí)會(huì)要求模塊有合法簽名否則直接被拒。安裝時(shí)如果沒注意這個(gè)裝完驅(qū)動(dòng)重啟后會(huì)看到類似這樣的提示Loading /var/lib/dkms/nvidia/530.41.03/build/nvidia.ko Error: Module nvidia not foundnvidia-smi執(zhí)行時(shí)報(bào)Failed to initialize NVML: Driver/library version mismatch也是這個(gè)原因的一種表現(xiàn)。解決方法有幾個(gè)最簡(jiǎn)單的就是進(jìn)BIOS把Secure Boot關(guān)掉。但有些服務(wù)器是托管的BIOS密碼都在機(jī)房管理員手里改不了。這種情況可以走模塊簽名流程生成自簽名密鑰然后用mokutil導(dǎo)入系統(tǒng)Linux內(nèi)核啟動(dòng)時(shí)會(huì)按MOK列表驗(yàn)證模塊簽名。生成簽名密鑰的流程openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj /CNNVIDIA-MODULE-SIGN/然后用mokutil --import MOK.der導(dǎo)入密鑰重啟后系統(tǒng)會(huì)進(jìn)入MOK管理界面按提示完成密碼確認(rèn)和密鑰加載。之后再用/usr/src/kernels/$(uname -r)/scripts/sign-file對(duì)編譯好的nvidia.ko、nvidia-modeset.ko等一堆內(nèi)核模塊逐一簽名。這個(gè)操作比較繁瑣但卻是唯一的正規(guī)路線。我分享一個(gè)經(jīng)驗(yàn)簽名腳本要對(duì)lib/modules/$(uname -r)/extra/nvidia下所有.ko文件執(zhí)行不要只簽主模塊。漏簽一個(gè)對(duì)應(yīng)的功能就會(huì)受限比如nvidia-modeset.ko沒簽顯示器驅(qū)動(dòng)就加載不上nvidia-uvm.ko沒簽CUDA統(tǒng)一內(nèi)存就不可用。2.4 DKMS方式的替代方案CentOS 7里還可以通過DKMS框架來管理NVIDIA驅(qū)動(dòng)模塊。DKMS的好處是當(dāng)內(nèi)核升級(jí)時(shí)驅(qū)動(dòng)模塊會(huì)自動(dòng)重編譯不用每次升級(jí)內(nèi)核后手動(dòng)重裝驅(qū)動(dòng)。yum install -y dkms裝好DKMS框架后在安裝NVIDIA run包時(shí)加上--dkms參數(shù)模塊文件會(huì)交給DKMS維護(hù)。裝完后每次系統(tǒng)通過yum升級(jí)內(nèi)核DKMS都會(huì)檢測(cè)到新內(nèi)核在重啟前自動(dòng)把NVIDIA模塊編譯好避免升級(jí)內(nèi)核后驅(qū)動(dòng)失效的尷尬。我在生產(chǎn)環(huán)境里更推薦這種方式因?yàn)榉?wù)器總要打安全補(bǔ)丁升級(jí)內(nèi)核的不會(huì)自動(dòng)重編驅(qū)動(dòng)的話每次升級(jí)都要心驚膽戰(zhàn)。DKMS方式有幾個(gè)注意點(diǎn)第一kernel-devel必須和當(dāng)前運(yùn)行內(nèi)核完全一致DKMS編譯就是依賴它第二導(dǎo)入MOK密鑰的頻率也要跟上內(nèi)核升級(jí)后簽名密鑰不會(huì)自動(dòng)變但模塊會(huì)重新編譯所以建議保留MOK密鑰文件方便重新簽名。第三NVIDIA驅(qū)動(dòng)run包在DKMS安裝模式下會(huì)往/usr/src/nvidia-530.41.03/寫入源碼不要手動(dòng)刪否則DKMS無從編譯。2.5 設(shè)置環(huán)境變量和持久化配置驅(qū)動(dòng)裝完后還需要設(shè)置CUDA相關(guān)的環(huán)境變量。雖然NVIDIA驅(qū)動(dòng)本身不依賴CUDA但跑深度學(xué)習(xí)框架時(shí)需要讓系統(tǒng)找到nvcc編譯器和CUDA運(yùn)行庫。在/etc/profile.d/下新建一個(gè)文件vim /etc/profile.d/cuda.sh寫入export PATH/usr/local/cuda-12.2/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda-12.2/lib64:$LD_LIBRARY_PATH保存后source /etc/profile生效。這里要注意/usr/local/cuda是一個(gè)軟鏈接指向?qū)嶋H安裝的CUDA版本目錄。系統(tǒng)里如果之前裝過別的版本軟鏈接指向可能不是你想要的需要確認(rèn)一下。ls -l /usr/local/ | grep cuda看清楚鏈接目標(biāo)別配了個(gè)幽靈路徑。還要處理電源管理問題GPU服務(wù)器功耗這塊需要配置持久化模式否則每次重啟NVIDIA驅(qū)動(dòng)都會(huì)恢復(fù)到默認(rèn)的非持久化模式GPU工作頻率管理混亂而且在某些虛擬化環(huán)境下會(huì)隨機(jī)掉卡。nvidia-smi -pm 1這條命令的意義是讓NVIDIA驅(qū)動(dòng)服務(wù)在后臺(tái)常駐管理GPU狀態(tài)。它會(huì)把電源管理配置寫入/etc/nvidia/目錄下的配置文件中SDK服務(wù)隨開機(jī)自動(dòng)啟動(dòng)不用每次手動(dòng)開。順便說一下加了-pm 1后nvidia-smi每次查詢GPU狀態(tài)的速度會(huì)明顯變快算是個(gè)意外之喜。3. 簡(jiǎn)單測(cè)試與性能驗(yàn)證裝完驅(qū)動(dòng)最要緊的就是立刻驗(yàn)證這一步能確認(rèn)驅(qū)動(dòng)是否真的對(duì)系統(tǒng)所有組件都兼容而不是僅僅“裝上沒報(bào)錯(cuò)”。3.1 nvidia-smi基礎(chǔ)信息檢查剛裝完驅(qū)動(dòng)先跑一下nvidia-smi這是判斷驅(qū)動(dòng)安裝是否成功的最直接手段。正常輸出會(huì)顯示顯卡名稱、驅(qū)動(dòng)版本、CUDA版本、顯存使用情況等。常見的問題場(chǎng)景是驅(qū)動(dòng)版本顯示出來了但CUDA Version顯示N/A或者顯示版本號(hào)但和預(yù)期不一致。如果是N/A說明CUDA toolkit沒有裝或者系統(tǒng)環(huán)境變量沒配對(duì)驅(qū)動(dòng)本身沒問題。根據(jù)經(jīng)驗(yàn)先檢查/usr/local/cuda軟鏈接是否存在再檢查L(zhǎng)D_LIBRARY_PATH里的路徑是否正確大多數(shù)情況是環(huán)境變量配置漏了。nvidia-smi下方會(huì)有一個(gè)進(jìn)程列表顯示當(dāng)前占用GPU的進(jìn)程。正常狀態(tài)下這里是空的但如果之前有過別的進(jìn)程運(yùn)行會(huì)看到殘留這個(gè)不用管如果顯示錯(cuò)誤進(jìn)程名或者PID異??梢杂胒user -v /dev/nvidia*查具體占用者。供電方面nvidia-smi -q -d POWER可以查看當(dāng)前功耗注意如果是老平臺(tái)的PCIe 2.0插槽供電限制可能導(dǎo)致GPU性能跑不滿但這類問題一般不是驅(qū)動(dòng)故障是硬件槽位約束。3.2 檢查內(nèi)核模塊加載狀態(tài)lsmod | grep nvidia正常情況下至少會(huì)有nvidia、nvidia_uvm、nvidia_drm、nvidia_modeset這幾個(gè)模塊輸出。其中nvidia_drm是顯示輸出模塊純計(jì)算場(chǎng)景下有沒有它不太影響CUDA計(jì)算但如果有桌面顯示需求它必須存在且正確加載。模塊加載情況的順序也值得注意。nvidia_modeset和nvidia_drm依賴nvidia父模塊如果父模塊沒加載成功后面這幾個(gè)也會(huì)顯示不可用。用dmesg | grep nvidia查看內(nèi)核日志能看到模塊加載的具體錯(cuò)誤信息。我遇到過nvidia_uvm模塊加載失敗的情況nvidia-smi能正常顯示但跑CUDA程序時(shí)統(tǒng)一內(nèi)存初始化報(bào)錯(cuò)。原因是有個(gè)特定的內(nèi)核參數(shù)匹配問題重新加載一次模塊就正常了modprobe -r nvidia_uvm nvidia_modeset nvidia_drm nvidia modprobe nvidia_uvm3.3 圖形渲染能力測(cè)試Ubuntu桌面用戶或者有大規(guī)??梢暬枨蟮呐笥芽梢栽谘b有圖形界面的CentOS 7機(jī)器上運(yùn)行g(shù)lxinfo查看OpenGL渲染器信息。如果顯示的是NVIDIA型號(hào)說明硬件加速已經(jīng)生效如果顯示的是llvmpipe或者M(jìn)esa說明還在用軟件模擬渲染性能會(huì)差太多。glxinfo | grep OpenGL renderer軟件渲染通常是因?yàn)闆]裝glxinfo工具或者X Server沒有正確加載NVIDIA的GLX模塊。如果顯示libGL error: failed to load driver: swrast那就是GL庫文件路徑混亂了常見的解決辦法是用--no-opengl-files參數(shù)重新跑一遍安裝流程把OpenGL文件的選擇權(quán)交給系統(tǒng)本身。3.4 計(jì)算能力測(cè)試與CUDA基礎(chǔ)驗(yàn)證如果CUDA toolkit已經(jīng)裝好最簡(jiǎn)單的計(jì)算測(cè)試就是寫一段CUDA的向量加法或者直接跑deviceQuery示例。這里有個(gè)更簡(jiǎn)單的方法用Python加PyTorch來驗(yàn)證import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0)) print(torch.cuda.get_device_capability(0)) a torch.randn(10000).cuda() b torch.randn(10000).cuda() c a b assert torch.allclose(c, a b, rtol1e-5) print(CUDA runtime test passed)PyTorch能正確輸出顯卡名稱和計(jì)算能力說明CUDA驅(qū)動(dòng)部分已經(jīng)工作正常。向量加法的結(jié)果驗(yàn)證能確保顯存讀寫沒有異常。在實(shí)驗(yàn)室機(jī)器上實(shí)測(cè)輸出計(jì)算能力是(7,5)一張Tesla V100級(jí)別的卡跑起來單精度乘加運(yùn)算快得出奇幾毫秒的運(yùn)算根本沒必要用性能計(jì)數(shù)器去測(cè)損耗直接用torch.cuda.synchronize()卡一下時(shí)間就能測(cè)出大致水平。真實(shí)場(chǎng)景中跑深度學(xué)習(xí)計(jì)算測(cè)試時(shí)要注意顯存占用torch.randn(10000).cuda()這種小規(guī)模計(jì)算占不了多少顯存但如果是大模型的加載測(cè)試顯存不夠時(shí)PyTorch會(huì)拋出CUDA out of memory錯(cuò)誤這個(gè)錯(cuò)誤和驅(qū)動(dòng)故障無關(guān)是要調(diào)batch size。3.5 用NVIDIA自帶工具做壓力測(cè)試驅(qū)動(dòng)包自帶的nvidia-bug-report.sh和nvidia-smi diag這些工具可以更深入地檢測(cè)GPU健康狀態(tài)。nvidia-smi -q -d PERFORMANCE nvidia-smi -q -d TEMPERATURE nvidia-smi -q -d MEMORY跑一次完整的顯存壓力測(cè)試可以用nvidia-smi -q -d ECC查看ECC糾錯(cuò)計(jì)數(shù)在深度學(xué)習(xí)訓(xùn)練環(huán)境中ECC計(jì)數(shù)如果持續(xù)增長(zhǎng)說明顯存有硬件問題需要立刻排查。另一個(gè)方法是編譯驅(qū)動(dòng)包里的NVIDIA CUDA Sample里面的bandwidthTest和deviceQuery示例非常適合驗(yàn)證計(jì)算和帶寬。make -C /usr/local/cuda/samples/1_Utilities/bandwidthTest ./bandwidthTest輸出結(jié)果中Host to Device和Device to Host的帶寬值如果遠(yuǎn)低于理論峰值或者波動(dòng)很大就要檢查PCIe通道是不是沒跑在滿速狀態(tài)。我遇到過一次顯卡插在PCIe 3.0 x4槽位上帶寬只有x16的五分之一裝驅(qū)動(dòng)時(shí)一切正常但訓(xùn)練速度非常慢。最后發(fā)現(xiàn)是主板上第二根PCIe插槽實(shí)際只有x4通道換槽后性能大幅提升。4. 常見問題與故障排查實(shí)錄驅(qū)動(dòng)裝多了總會(huì)遇到各種問題這一節(jié)我把遇到的典型故障和排查路徑整理成速查表也把幾條重要的排查思路單獨(dú)講清楚。4.1 安裝完成后啟動(dòng)卡在登錄界面或黑屏現(xiàn)象重啟后無法進(jìn)入系統(tǒng)顯示器黑屏或者卡在登錄界面循環(huán)跳轉(zhuǎn)。在CentOS 7這種以X Server為主的系統(tǒng)里最常見的原因是OpenGL庫被覆蓋。解決辦法分兩種路徑如果是已經(jīng)裝好了驅(qū)動(dòng)系統(tǒng)起不來進(jìn)單用戶模式重裝驅(qū)動(dòng)加上--no-opengl-files參數(shù)如果驅(qū)動(dòng)還沒裝只是預(yù)先配置了nouveau黑名單導(dǎo)致桌面起不來那就進(jìn)字符模式把/etc/modprobe.d/blacklist-nouveau.conf里內(nèi)容注釋掉先恢復(fù)系統(tǒng)再重新規(guī)劃安裝。新老司機(jī)都要記住純計(jì)算服務(wù)器上完全沒必要裝OpenGL相關(guān)的文件顯存計(jì)算和OpenGL沒有任何關(guān)系驅(qū)動(dòng)包帶的那份OpenGL庫是針對(duì)桌面Linux用戶寫的服務(wù)器上加了它反而容易出事。4.2 NVIDIA-SMI報(bào)錯(cuò)Failed to initialize NVMLFailed to initialize NVML: Driver/library version mismatch是頻率最高的報(bào)錯(cuò)。原因通常是驅(qū)動(dòng)/內(nèi)核模塊和用戶態(tài)庫的版本不一致比如內(nèi)核里還是老版本的nvidia.ko而用戶態(tài)的libnvidia-ml.so已經(jīng)被更新到新版了。排查思路nvidia-smi --version cat /proc/driver/nvidia/version兩者版本對(duì)不上就要用lsmod | grep nvidia看內(nèi)核模塊狀態(tài)用modprobe -r nvidia卸載再重新加載。如果重新加載后直接被拒絕需要重啟系統(tǒng)進(jìn)入新內(nèi)核后用干凈的方式重新加載模塊。另一種類似報(bào)錯(cuò)是NVML library version mismatch這種多數(shù)是驅(qū)動(dòng)run包重裝但沒有徹底清理舊文件導(dǎo)致的。裝新版本前建議用nvidia-uninstall卸載一遍或者手動(dòng)刪掉/usr/lib64/libnvidia*下的舊庫文件再重裝。4.3 內(nèi)核升級(jí)后驅(qū)動(dòng)失效CentOS 7如果通過yum update升級(jí)了內(nèi)核重啟后往往發(fā)現(xiàn)nvidia-smi無法運(yùn)行因?yàn)樾聝?nèi)核需要重新編譯NVIDIA內(nèi)核模塊。這就是前面提到DKMS價(jià)值的活案例沒配DKMS就要手動(dòng)把驅(qū)動(dòng)run包重新執(zhí)行一遍。重新執(zhí)行的方法很簡(jiǎn)單./NVIDIA-Linux-x86_64-530.41.03.run --silent如果沒勾DKMS記得先檢查kernel-devel版本是否匹配新內(nèi)核不匹配先裝kernel-devel-$(uname -r)。升級(jí)內(nèi)核這個(gè)操作還有個(gè)大坑CentOS 7的yum update默認(rèn)會(huì)保留多個(gè)內(nèi)核版本重啟時(shí)如果不小心選錯(cuò)了舊內(nèi)核nvidia-smi也會(huì)報(bào)版本不匹配錯(cuò)誤。所以升級(jí)完內(nèi)核重啟時(shí)最好確認(rèn)一下當(dāng)前啟動(dòng)的是哪個(gè)內(nèi)核版本uname -r一查便知。4.4 編譯錯(cuò)誤Kernel header not found安裝run包時(shí)在編譯階段報(bào)Kernel header not found這個(gè)錯(cuò)誤很多新手看到就慌。排查方向很簡(jiǎn)單yum list installed | grep kernel-devel ls /usr/src/kernels/kernel-devel沒裝或者版本和uname -r不一致。有時(shí)候yum install kernel-devel會(huì)自動(dòng)裝一個(gè)最新版本的內(nèi)核頭文件但這個(gè)最新版本和當(dāng)前運(yùn)行的內(nèi)核不是同一個(gè)這就會(huì)導(dǎo)致問題。解決方法是明確指定版本號(hào)安裝yum install -y kernel-devel-$(uname -r)如果當(dāng)前運(yùn)行的內(nèi)核版本在yum源里找不到對(duì)應(yīng)的kernel-devel包極大概率是機(jī)器內(nèi)核被手動(dòng)升級(jí)過了而CentOS 7的基礎(chǔ)yum源沒有新到那個(gè)內(nèi)核版本的開發(fā)包需要額外添加源或者直接去官網(wǎng)鏡像站點(diǎn)找那個(gè)版本的RPM文件。4.5 CUDA版本與驅(qū)動(dòng)版本不匹配CUDA運(yùn)行時(shí)對(duì)驅(qū)動(dòng)版本有下限要求比如CUDA 12.2要求驅(qū)動(dòng)版本530.30.0。驅(qū)動(dòng)版本太老時(shí)運(yùn)行CUDA程序會(huì)報(bào)CUDA driver version is insufficient for CUDA runtime version。NVIDIA官方有個(gè)CUDA兼容矩陣表格列出每個(gè)CUDA版本要求的最低驅(qū)動(dòng)版本。查這張表再?zèng)Q定是升級(jí)驅(qū)動(dòng)還是降級(jí)CUDA不要憑感覺來。我遇到過CUDA庫版本和驅(qū)動(dòng)版本都滿足要求但運(yùn)行程序仍報(bào)這個(gè)錯(cuò)的情況最后發(fā)現(xiàn)是LD_LIBRARY_PATH里混入了多個(gè)CUDA版本的路徑系統(tǒng)優(yōu)先加載了舊CUDA運(yùn)行庫。用ldd檢查當(dāng)前程序的動(dòng)態(tài)庫依賴就能發(fā)現(xiàn)ldd /path/to/your_binary | grep libcuda正常應(yīng)顯示libcuda.so.1如果是libcuda.so.530.41.03這類帶完整驅(qū)動(dòng)版本號(hào)的庫文件說明庫路徑混亂了需要調(diào)整LD_LIBRARY_PATH。4.6 顯卡掉卡與PCIe鏈路異常有些雙卡甚至四卡服務(wù)器會(huì)遇到某張卡間歇性檢測(cè)不到nvidia-smi里卡的數(shù)量時(shí)多時(shí)少。這個(gè)問題在虛擬化環(huán)境下特別常見宿主機(jī)的PCIe拓?fù)涓綦x不徹底會(huì)出現(xiàn)物理服務(wù)器通常沒那么容易掉卡但PCIe插槽接觸不良仍然可能。排查分兩步lspci | grep -i nvidia nvidia-smi -L第一句看系統(tǒng)是否識(shí)別了所有卡第二句看驅(qū)動(dòng)是否管理了所有卡。如果lspci能看到但驅(qū)動(dòng)管理不到可以用nvidia-smi -r重置這張卡或者用nvidia-smi --gpu-reset強(qiáng)制重置指定GPU。物理接觸不良的情況關(guān)機(jī)斷電重新插拔顯卡和供電線才是終極辦法這個(gè)問題在密集機(jī)架環(huán)境中出現(xiàn)概率不小移動(dòng)服務(wù)器后經(jīng)常遇到裝了再好的驅(qū)動(dòng)也解決不了接觸不良。5. 實(shí)戰(zhàn)心得與后續(xù)優(yōu)化建議跑了這么多年Linux服務(wù)器裝NVIDIA驅(qū)動(dòng)像是每個(gè)運(yùn)維都要走過的獨(dú)木橋。這里把后續(xù)值得做的事情和最終的體會(huì)寫一下給新接觸GPU服務(wù)器的朋友一個(gè)落地的收尾。5.1 單卡與多卡環(huán)境的差異單卡服務(wù)器裝驅(qū)動(dòng)相對(duì)簡(jiǎn)單多卡環(huán)境在多卡互聯(lián)、中斷路由、PCIe帶寬分配上會(huì)有更多需要檢查的點(diǎn)。多卡環(huán)境裝好驅(qū)動(dòng)后nvidia-smi topo -m可以查看GPU之間的拓?fù)潢P(guān)系是NVLink直連還是走PCIe交換。運(yùn)行深度學(xué)習(xí)任務(wù)時(shí)盡量讓通信頻繁的進(jìn)程跑在同一根PCIe交換機(jī)下的GPU組合上延遲會(huì)低不少。雙卡環(huán)境還有一個(gè)常見問題系統(tǒng)默認(rèn)的MMIO映射空間不夠兩塊卡共用一個(gè)中斷分組會(huì)導(dǎo)致性能異常。這種問題一般通過內(nèi)核參數(shù)pcirealloc解決配置到/etc/default/grub的CMDLINE_LINUX里執(zhí)行g(shù)rub2-mkconfig -o /boot/grub2/grub.cfg后重啟生效。5.2 驅(qū)動(dòng)程序占用的顯存和MIG配置nvidia-smi啟動(dòng)后每個(gè)GPU會(huì)預(yù)留一部分顯存給驅(qū)動(dòng)上下文顯存越大預(yù)留比例越高。初步估算驅(qū)動(dòng)預(yù)留顯存通常是數(shù)十到兩三百M(fèi)B的量級(jí)對(duì)訓(xùn)練任務(wù)只占用個(gè)位數(shù)GB顯存的時(shí)候影響不明顯但如果是小顯存卡跑模型這個(gè)開銷不能忽視。預(yù)留的顯存可以在nvidia-smi輸出里看到分成FB Memory Usage的used項(xiàng)。新一代專業(yè)卡支持MIG多實(shí)例GPU可以把一塊物理GPU切成多個(gè)獨(dú)立分區(qū)每個(gè)分區(qū)擁有獨(dú)立的顯存和計(jì)算單元。配置MIG后面向多租戶場(chǎng)景非常有用但要注意MIG開啟后驅(qū)動(dòng)必須在root權(quán)限下運(yùn)行nvidia-smi -mig 1啟用并且CUDA版本要支持MIG特性。跑深度學(xué)習(xí)多任務(wù)分片時(shí)這種方式能大幅提升單卡資源利用率。5.3 推薦自動(dòng)監(jiān)控腳本方案生產(chǎn)環(huán)境建議寫一個(gè)簡(jiǎn)單的Shell腳本監(jiān)控GPU的功耗、溫度和顯存使用出現(xiàn)異常自動(dòng)重啟驅(qū)動(dòng)或記錄日志。分享一個(gè)簡(jiǎn)化版的監(jiān)控思路#!/bin/bash GPU_TEMP$(nvidia-smi --query-gputemperature.gpu --formatcsv,noheader | awk {sum$1} END {print sum/NR}) if [ $GPU_TEMP -gt 85 ]; then echo $(date) GPU temperature $GPU_TEMP 85, please check cooling /var/log/gpu_monitor.log fi腳本思路很簡(jiǎn)單做不做取決于現(xiàn)場(chǎng)環(huán)境。個(gè)人建議如果機(jī)器放在機(jī)房里散熱沒把握或者跑的是長(zhǎng)時(shí)間訓(xùn)練任務(wù)這類監(jiān)控一定不能省。至少每周看一眼nvidia-smi的功耗和溫度走勢(shì)花不了兩分鐘能省掉不少半夜被叫起來處理故障的麻煩。5.4 安裝之后需要養(yǎng)成的習(xí)慣裝機(jī)完成不是終點(diǎn)日常維護(hù)才是重點(diǎn)。根據(jù)個(gè)人經(jīng)驗(yàn)裝機(jī)后會(huì)再養(yǎng)成的習(xí)慣包括工具鏈全家桶保持干凈kernel-devel和gcc這些編譯組件不要隨便卸載指不定哪天升級(jí)內(nèi)核就要用。安裝驅(qū)動(dòng)時(shí)生成的各種備份文件不要急著刪比如initramfs的bak文件留著占不了多少空間關(guān)鍵時(shí)刻能救命。涉及/etc/modprobe.d/和/etc/profile.d/的修改記得寫注釋表明改了什么和原因不然三個(gè)月后你再回來看自己寫的配置文件多半會(huì)一頭霧水。更重要的一點(diǎn)CentOS 7已經(jīng)在逐步進(jìn)入維護(hù)末期如果新裝機(jī)項(xiàng)目還在規(guī)劃階段建議同步評(píng)估新版系統(tǒng)的遷移路徑。NVIDIA驅(qū)動(dòng)在新系統(tǒng)上裝機(jī)流程更順因?yàn)樾掳嫦到y(tǒng)自帶的內(nèi)核模塊簽名機(jī)制和DKMS管理更成熟不用像CentOS 7里這樣費(fèi)勁手動(dòng)管理模塊。但如果短期跑的是存量CentOS 7環(huán)境這套流程穩(wěn)定用幾年是沒問題的。5.5 回歸一下裝驅(qū)動(dòng)這件事的心態(tài)把驅(qū)動(dòng)裝上nvidia-smi能打印出來訓(xùn)練能跑起來這只是起步。真正的價(jià)值在于通過這次折騰把系統(tǒng)底層、顯卡硬件、內(nèi)核模塊之間的關(guān)系理清楚了后續(xù)再遇到類似問題就不再是黑盒試探而是有思路可循的排查過程。我個(gè)人在實(shí)際操作中的體會(huì)是裝NVIDIA驅(qū)動(dòng)這件事情最大的敵人不是復(fù)雜的技術(shù)難點(diǎn)而是心急。每一步都驗(yàn)證過了再往前走比一口氣跑完所有命令要穩(wěn)妥得多。尤其是重啟這個(gè)環(huán)節(jié)每次重啟前想清楚要不要備份、要不要改啟動(dòng)項(xiàng)、確認(rèn)哪些服務(wù)會(huì)受影響這些習(xí)慣能省掉的麻煩遠(yuǎn)超你的想象。