GPU程式設計(一):Ubuntu下的CUDA8.0環境搭建

Sorrower發表於2018-10-19

目錄

  • 前言
  • 開發環境一覽
  • 顯示卡驅動安裝
  • 下載驅動
  • 禁用nouveau
  • 安裝驅動
  • 安裝CUDA8.0
  • 第一個CUDA程式
  • 向世界問好
  • 最後

前言

在Linux下安裝驅動真的不是一件簡單的事情, 尤其是顯示卡驅動, 一失敗直接進不去系統都是很可能的. 我在經歷了無數折磨之後終於搭起了CUDA程式設計環境. 我是很心水老黃的, 但是, 我還是想說”So, Nvidia: FUCK YOU!”(Linux之父原話)(手動滑稽).

Linux之父

2007年6月23日 NVIDIA公司釋出了CUDA, 透過這個技術, 使用者可利用NVIDIA的GeForce 8以後的GPU和較新的Quadro GPU進行計算. 亦是首次可以利用GPU作為C-編譯器的開發環境. 近年來, GPU最成功的一個應用就是深度學習領域, 基於GPU的平行計算已經成為訓練深度學習模型的標配.

GPU並不是一個獨立執行的計算平臺, 而需要與CPU協同工作, 可以看成是CPU的協處理器, 因此當我們在說GPU平行計算時, 其實是指的基於CPU + GPU的異構計算架構. 在異構計算架構中, GPU與CPU通過PCIe匯流排連線在一起來協同工作, CPU所在位置稱為為主機端(host), 而GPU所在位置稱為裝置端(device), 如下圖所示:

HOST-DEVICE

CUDA技術有下列幾個優點:

  • 分散讀取–程式碼可以從儲存器的任意地址讀取
  • 統一虛擬記憶體(CUDA 4)
  • 共享儲存器–CUDA公開一個快速的共享儲存區域(每個處理器48K), 使之在多個程式之間共享.其作為一個使用者管理的快取記憶體,比使用紋理查詢可以得到更大的有效頻寬.
  • 與GPU之間更快的下載與回讀
  • 全面支援整型與位操作, 包括整型紋理查詢

開發環境一覽

  • GPU: NVIDIA GT 750M
  • OS: UBUNTU 14.04.1LTS 64位(之後會說為什麼選這個版本, 16.04流程基本類似, 但是要注意核心版本)

用指令看下英偉達顯示卡:

lspci | grep -i nvidia

NVIDIA GT 750M

當你搭建完成環境之後, 可以用程式碼檢視硬體資訊, 自己寫或者官方的例子, 我的NVIDIA GT 750M資訊顯示如下圖, 當然可以直接到英偉達官網檢視顯示卡資訊.

顯示卡資訊

官方例子顯示卡資訊


顯示卡驅動安裝

千萬不要用UBUNTU附加驅動裡提供的顯示卡驅動!!!
千萬不要用UBUNTU附加驅動裡提供的顯示卡驅動!!!
千萬不要用UBUNTU附加驅動裡提供的顯示卡驅動!!!
一般來說, 你會遇到一些奇怪的問題, 當然, 錦鯉是不會出問題的(手動滑稽).
這是第一個坑點, 大體有三種展現方式:

  • 裝完重啟進不去系統, 卡住ubuntu載入頁面;
  • 無限登入;
  • 裝好了, 進入了系統, 然後輸入nvidia-smi指令沒有任何反應. 正常情況會彈出一張表, 如下所示:

nvidia-smi


下載驅動

行了, 來說說我的實操:
首先到官網下載顯示卡驅動, 比方說我是GT 750M, 作業系統是64位Linux, 我就找對應的版本進行下載.

下載驅動

刪掉以往的驅動. 注意, 就算你啥都沒裝, 這步也是無害的.

sudo apt-get remove --purge nvidia*

更新並安裝一些需要的庫, 先裝這麼多, 之後裝CUDA還有一波.

sudo apt-get update
sudo apt-get install dkms build-essential linux-headers-generic

禁用nouveau

開啟blacklist.conf, 在最後加入禁用nouveau的設定, 這是一個開源驅動, 如圖所示:

sudo vim /etc/modprobe.d/blacklist.conf
blacklist nouveau
blacklist lbm-nouveau
options nouveau modeset=0
alias nouveau off
alias lbm-nouveau off

禁用nouveau

禁用nouveau核心模組

echo options nouveau modeset=0
sudo update-initramfs -u

重啟. 如果執行如下指令沒用列印出任何內容, 恭喜你, 禁用nouveau成功了.

lsmod | grep nouveau

安裝驅動

來到tty1(快捷鍵ctrl + alt + f1,如果沒反應就f1-f7一個個試, 不同Linux, 按鍵會略有不同). 執行如下指令關閉圖形介面.

sudo service lightdm stop

安裝驅動, 注意有坑, 一定要加-no-opengl-files, 不加這個就算安裝成功, 也會出現無限登入問題.

sudo chmod u+x NVIDIA-Linux-x86_64-390.87.run 
sudo ./NVIDIA-Linux-x86_64-390.87.run –no-opengl-files

如果你已經裝了, 但是沒有加-no-opengl-files, 按照如下操作可以救一下.

sudo ./NVIDIA-Linux-x86_64-390.87.run –uninstall
sudo ./NVIDIA-Linux-x86_64-390.87.run –no-opengl-files

重啟. 用nvidia-smi指令試一下, 如果看到類似下圖, 恭喜你, 驅動安裝成功. 或者看到附加驅動顯示繼續使用手動安裝的驅動.

nvidia-smi

附加驅動


安裝CUDA8.0

先來補庫.

sudo apt-get install freeglut3-dev libx11-dev libxmu-dev libxi-dev libgl1-mesa-glx libglu1-mesa libglu1-mesa-dev

官網下載要的CUDA版本, 我這裡是8.0第二個版本, 下載runfile(local)版本, 如下圖所示:

安裝CUDA8.0

md5檢測一下, 不合格要重新下載. 下圖是我的檢測結果:

md5sum cuda_8.0.61_375.26_linux.run

md5檢測

再次關閉圖形介面

sudo service lightdm stop

安裝時候依舊要加-no-opengl-files引數, 之後一路預設就好.

sudo sh cuda_8.0.61_375.26_linux.run –no-opengl-files

然後會看到三個installed.

開啟圖形介面

sudo service lightdm start

這裡又有一個坑, 如果是14.04.5, 我到這一步就開啟不了了, 後來換成14.04.1就可以了, 總之核心也要小心選擇.

執行如下命令, 如果顯示如圖3個資料夾, 恭喜你.

ls /dev/nvidia*

如果少了或者都找不到, 還有一些操作要做. 用vim建立一個xxx.sh(名字隨意), 輸入以下內容:

#!/bin/bash

/sbin/modprobe nvidia

if [ "$?" -eq 0 ]; then
  # Count the number of NVIDIA controllers found.
  NVDEVS=`lspci | grep -i NVIDIA`
  N3D=`echo "$NVDEVS" | grep "3D controller" | wc -l`
  NVGA=`echo "$NVDEVS" | grep "VGA compatible controller" | wc -l`

  N=`expr $N3D + $NVGA - 1`
  for i in `seq 0 $N`; do
    mknod -m 666 /dev/nvidia$i c 195 $i
  done

  mknod -m 666 /dev/nvidiactl c 195 255

else
  exit 1
fi

/sbin/modprobe nvidia-uvm

if [ "$?" -eq 0 ]; then
  # Find out the major device number used by the nvidia-uvm driver
  D=`grep nvidia-uvm /proc/devices | awk `{print $1}``

  mknod -m 666 /dev/nvidia-uvm c $D 0
else
  exit 1
fi

執行後就會看到3個資料夾.

sudo chmod +x xxx.sh
sudo ./xxx.sh
ls /dev/nvidia*
/dev/nvidia0  /dev/nvidiactl  /dev/nvidia-uvm

然後寫入rc.local中, 如圖所示:

sudo vim /etc/rc.local

rc.local

開啟環境配置檔案

sudo vim /etc/profile

最後寫入:

export PATH=/usr/local/cuda-8.0/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64:$LD_LIBRARY_PATH

儲存退出, 並其生效.

source /etc/profile

然後就能看到了.

執行一些檢測命令, 如果和我顯示的類似, 恭喜你, 環境配置完成.

cat /proc/driver/nvidia/version
nvcc -V

檢測

當然, 你可以編譯NVIDIA Samples中的例子, 然後執行. 最常見的就是deviceQuery了. 走兩步:

deviceQuery


第一個CUDA程式

之前在開發環境部分展示過一個小栗子, 來看看具體程式碼吧~

vim Device.cu
#include <stdio.h>
int main() {
        int nDevices;

        cudaGetDeviceCount(&nDevices);
        for (int i = 0; i < nDevices; i++) {
                cudaDeviceProp prop;
                cudaGetDeviceProperties(&prop, i);
                printf("Device Num: %d
", i);
                printf("Device name: %s
", prop.name);
                printf("Device SM Num: %d
", prop.multiProcessorCount);
                printf("Share Mem Per Block: %.2fKB
", prop.sharedMemPerBlock / 1024.0);
                printf("Max Thread Per Block: %d
", prop.maxThreadsPerBlock);
                printf("Memory Clock Rate (KHz): %d
",
                   prop.memoryClockRate);
                printf("Memory Bus Width (bits): %d
",
                   prop.memoryBusWidth);
                printf("Peak Memory Bandwidth (GB/s): %.2f

",
                   2.0 * prop.memoryClockRate * (prop.memoryBusWidth / 8) / 1.0e6);
        }
        return 0;
}
nvcc Device.cu -o Device.o
./Device.o

第一個CUDA程式


向世界問好

沒有Hello, world!怎麼行? 具體說明要到下期了哦~

#include <stdio.h>

__global__ void helloFromGPU ()
{
        printf("Hello, world! from GPU!
");
}

int main()
{
        printf("Hello, world! from CPU!
");

        helloFromGPU <<<2, 10>>>();

        cudaDeviceReset();

        return 0;
}

Hello, world!


最後

事實上, 由於沒有以GPU為單獨核心的終端, 所以GPU程式設計其實都是CPU + GPU結構的, CPU負責複雜的序列, GPU負責平行計算. 好了, 喜歡記得點贊哦, 有意見或者建議評論區見~


相關文章