cudalinux編譯
首先創建一個soTest的文件夾,裡面有兩個文件deviceQuery.cpp, t.cpp。
deviceQuery.cpp的代碼可以參考CUDASDKt.cpp的源代碼如下:
#includeintcudev(intargc,char**argv);
intmain(intargc,char**argv)
{
cudev(argc,argv);
return0;
}
然後在當前目錄下輸下命令
B. 什麼是CUDA
CUDA(Compute Unified Device Architecture),顯卡廠商NVidia推出的運算平台。 CUDA™是一種由NVIDIA推出的通用並行計算架構,該架構使GPU能夠解決復雜的計算問題。 它包含了CUDA指令集架構(ISA)以及GPU內部的並行計算引擎。
隨著顯卡的發展,GPU越來越強大,而且GPU為顯示圖像做了優化。在計算上已經超越了通用的CPU。如此強大的晶元如果只是作為顯卡就太浪費了,因此NVidia推出CUDA,讓顯卡可以用於圖像計算以外的目的。
簡單來講,比如通過CUDA架構,視頻播放軟體可以充分挖掘NVIDIA系列顯卡的GPU並行計算能力,輕松進行高清影片的播放,與軟體高清解碼相比,CPU佔用可以下降一半以上。當然,CUDA的應用領域絕不僅僅是視頻、圖形、游戲,包括各種3D和建模,醫療、能源、科學研究等,到處都可見到這種技術架構的應用。
支持CUDA的硬體環境需要有NVidia GF8系列及以上型號的顯卡,並且安裝185版本以上的顯卡驅動程序。以QQ影音播放器來講,要想開啟CUDA硬體解碼加速,可以打開QQ影音的「播放器設置」,進入「高清加速」面板,在「硬體優化」中選擇「自定義優化模式」,然後在「濾鏡配置」中的「視頻解碼器」中自定義選擇相應的「QQ CUDA Video Decoder(CUDADecFilter.ax)」即可。而關閉CUDA加速,只需取消選擇「QQ CUDA Video Decoder(CUDADecFilter.ax)」,或者切換到「智能高清模式」或「穩定兼容模式」通過這種高清解碼定義的開啟,並不是說你的畫質能夠提升多少,而是提升高清視頻播放時的流暢以及降低CPU的佔用。這個時候,節約下來的CPU空間,可以允許你再去做別的工作,這樣就會大大提升你的工作效率,而不至於除了看視頻,其他的什麼都不能做了。
C. 如何在kali linux中安裝英偉達內核模塊cuda和pyrit
安裝cuda以及nvidia驅動
這慶吵一步比較簡單,安裝之前,推薦大家編輯一下/etc/apt/source.list文件鎮差毀,把國外的源注釋掉換成國內科大的,下載比較快。科大源的地址如下
deb http://mirrors.ustc.e.cn/kali kali main non-free contrib
deb-src http://mirrors.ustc.e.cn/kali kali main non-free contrib
deb http://mirrors.ustc.e.cn/kali-security kali/updates main contrib non-free
設置完之後,執行以下命令安裝
apt-get update
apt-get install nvidia-detect nvidia-libopencl1 nvidia-opencl-common nvidia-support nvidia-opencl-icd nvidia-visual-profiler nvidia-glx nvidia-installer-cleanup nvidia-kernel-common nvidia-smi nvidia-alternative nvidia-opencl-dev libglx-nvidia-alternatives nvidia-kernel-dkms nvidia-cuda-toolkit nvidia-vdpau-driver nvidia-xconfig glx-alternative-nvidia libgl1-nvidia-alternatives nvidia-settings libgl1-nvidia-glx xserver-xorg-video-nvidia libcublas4 libcudart4 libcufft4 libnpp4 libnvidia-compiler libcuda1 libcuinj4 libnvidia-ml1 libxvmcnvidia1 libcusparse4 libcurand4 python-pycuda-doc python-pycuda-headers python-pycuda nvidia-cuda-doc nvidia-cuda-gdb
由於包比較多可能有點慢,安裝過程會彈出兩個窗口需要確認,直接OK就好,執行完之後toolkit和驅動都裝上了,然後把一些變數寫入系統,在/root/.bashrc最後面加上下面一段
PATH=$PATH:/usr/lib/nvidia-cuda-toolkit/bin
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/nvidia-cuda-toolkit/lib:/lib
export PATH
export LD_LIBRARY_PATH
可以執行一下ldconfig馬上生效,不過反正都要重啟一次的了,重啟。
安裝pyrit-cuda
下面重新編譯個pyrit來試一試使用GPU。下載pyrit的地址是:
https://code.google.com/p/pyrit/downloads/list
我們需要下載pyrit-0.4.0.tar.gz和cpyrit-cuda-0.4.0.tar.gz,下載完之後,安裝一下編譯所需要的工具
atp-get install libpcap-dev python2.7-dev
解壓pyrit-0.4.0.tar.gz並且安裝
tar -xzvf pyrit-0.4.0.tar.gz
cd pyrit-0.4.0
python setup.py build
python setup.py install
解壓cpyrit-cuda-0.4.0.tar.gz
tar -xzvf cpyrit-cuda-0.4.0.tar.gz
cd cpyrit-cuda-0.4.0
這里需要進行一些改動,編輯setup.py,把第35行
for path in ('/usr/local/cuda', '/opt/cuda'):
改成
for path in ('/usr/local/cuda','御備/usr/lib/nvidia-cuda-toolkit','/opt/cuda'):
免得安裝程序找不到nvcc
然後就安裝
python setup.py build
python setup.py install
安裝完,運行一下
pyrit list_cores
應該能看到GPU了,類似
#1: 'CUDA-Device #1 'GeForce 8400 GS''
#2: 'CPU-Core (SSE2)'
#3: 'CPU-Core (SSE2)'
#4: 'CPU-Core (SSE2)'
#5: 'CPU-Core (SSE2)'
#6: 'CPU-Core (SSE2)'
#7: 'CPU-Core (SSE2)'
#8: 'CPU-Core (SSE2)'
安裝optimus
把源Key取回來
wget -O - http://suwako.nomanga.net/suwako.asc | apt-key add -
在/etc/apt/source.list中加入Bumblebee的源
deb http://suwako.nomanga.net/debian sid main contrib
deb-src http://suwako.nomanga.net/debian sid main
然後執行安裝
apt-get update
apt-get install bumblebee bumblebee-nvidia
安裝完畢,把root加入bemblebe組,然後重啟
adser root bumblebee
重啟完畢可以測試一下,分別運行
glxspheres
optirun glxspheres
可以看到幀數是不同的
D. linux中哪些工具可以測試cuda程序,監控gpu內存性能
nvcc 編譯代碼
nvcc -o squareSum squareSum.cu運行結果:
CUDA initialized.
(GPU) sum:29909398 time:787124792
(CPU) sum:29909398 time:10000
從執行的結果可以看出, GPU 中運行的程序居然要比 CPU 中的消耗的時鍾周期還要多得多。這是有原因的。
因為程序之中並沒有使用 CUDA 並行執行的優勢。
這里分析一下 GPU 運行的性能。
此 GPU 消耗的時鍾周期: 787124792 cycles
GeForce G 103M 的 clockRate: 1.6 GHz
所以可以計算出 GPU 上運行時間是: 時鍾周期 / clockRate = 0.49195 s
1 M 個 int 型數據有 4M Byte 的數據量,實際使用的 GPU 內存帶寬是:數據量 / 運行時間 = 8.13 MB/s
可見這個程序沒有很好的發揮 GPU 的性能,使用的內存帶寬很小。
沒有有效利用 GPU 性能的原因???
在 CUDA 中,一般的數據復制到的顯卡內存的部份,稱為 global memory。這些內存是沒有 cache 的,而且,存取 global memory 所需要的時間(即 latency)是非常長的,通常是數百個 cycles。
由於我們的程序只有一個 thread,所以每次它讀取 global memory 的內容,就要等到實際讀取到數據、累加到 sum 之後,才能進行下一步。這就是為什麼它的表現會這么的差。實際上 GPU 一直在等待上一個數據運行的結束,然後再拷貝一個內存數據,所以使用的時鍾周期自然就長了。
由於 global memory 沒有 cache,所以要避開巨大的 latency 的方法,就是要利用大量的 threads。假設現在有大量的 threads 在同時執行,那麼當一個 thread 讀取內存,開始等待結果的時候,GPU 就可以立刻切換到下一個 thread,並讀取下一個內存位置。因此,理想上當 thread 的數目夠多的時候,就可以完全把 global memory 的巨大 latency 隱藏起來了。
E. linux下CUDA程序一般怎麼編譯
有以下步驟:
1.源程序的編譯
在Linux下面,如果要編譯一個C語言源程序,我們要使用GNU的gcc編譯器. 下面
我們以一個實例來說明如何使用gcc編譯器.
假設我們有下面一個非常簡單的源程序(hello.c):
int main(int argc,char **argv)
{
printf("Hello Linux\n");
}
要編譯這個程序,我們只要在命令行下執行:
gcc -o hello hello.c
gcc 編譯器就會為我們生成一個hello的可執行文件.執行./hello就可以看到程
序的輸出結果了.命令行中 gcc表示我們是用gcc來編譯我們的源程序,-o 選項表示
我們要求編譯器給我們輸出的可執行文件名為hello 而hello.c是我們的源程序文件.
gcc編譯器有許多選項,一般來說我們只要知道其中的幾個就夠了. -o選項我們
已經知道了,表示我們要求輸出的可執行文件名. -c選項表示此慧我們只要求編譯器輸出
目標代碼,而不必要輸出可執行文件. -g選項拍扒差表示我們要求編譯器在編譯的時候提
供我們以後對程序進行調試的信息.
知道了這三個選項,我們就可以編譯我們自己所寫的簡單的源程序了,如果你
想要知道更多的選項,可以查看gcc的幫助文檔,那裡有著許多對其它選項的詳細說
明.
2.Makefile的編寫
假設我們有下面這樣的一個程序,源代碼如下襲皮:
#include "mytool1.h"
#include "mytool2.h"
int main(int argc,char **argv)
{
mytool1_print("hello");
mytool2_print("hello");
}
#ifndef _MYTOOL_1_H
#define _MYTOOL_1_H
void mytool1_print(char *print_str);
#endif
#include "mytool1.h"
void mytool1_print(char *print_str)
{
printf("This is mytool1 print %s\n",print_str);
}
#ifndef _MYTOOL_2_H
#define _MYTOOL_2_H
void mytool2_print(char *print_str);
#endif
#include "mytool2.h"
void mytool2_print(char *print_str)
{
printf("This is mytool2 print %s\n",print_str);
}
當然由於這個程序是很短的我們可以這樣來編譯
gcc -c main.c
gcc -c mytool1.c
gcc -c mytool2.c
gcc -o main main.o mytool1.o mytool2.o
這樣的話我們也可以產生main程序,而且也不時很麻煩.但是如果我們考慮一
下如果有一天我們修改了其中的一個文件(比如說mytool1.c)那麼我們難道還要重
新輸入上面的命令?也許你會說,這個很容易解決啊,我寫一個SHELL腳本,讓她幫我
去完成不就可以了.是的對於這個程序來說,是可以起到作用的.但是當我們把事情
想的更復雜一點,如果我們的程序有幾百個源程序的時候,難道也要編譯器重新一
個一個的去編譯?
為此,聰明的程序員們想出了一個很好的工具來做這件事情,這就是make.我們
只要執行以下make,就可以把上面的問題解決掉.在我們執行make之前,我們要先
編寫一個非常重要的文件.--Makefile.對於上面的那個程序來說,可能的一個
Makefile的文件是:
# 這是上面那個程序的Makefile文件
main:main.o mytool1.o mytool2.o
gcc -o main main.o mytool1.o mytool2.o
main.o:main.c mytool1.h mytool2.h
gcc -c main.c
mytool1.o:mytool1.c mytool1.h
gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
gcc -c mytool2.c
有了這個Makefile文件,不過我們什麼時候修改了源程序當中的什麼文件,我們
只要執行make命令,我們的編譯器都只會去編譯和我們修改的文件有關的文件,其
它的文件她連理都不想去理的.
下面我們學習Makefile是如何編寫的.
在Makefile中也#開始的行都是注釋行.Makefile中最重要的是描述文件的依賴
關系的說明.一般的格式是:
target: components
TAB rule
第一行表示的是依賴關系.第二行是規則.
比如說我們上面的那個Makefile文件的第二行
main:main.o mytool1.o mytool2.o
表示我們的目標(target)main的依賴對象(components)是main.o mytool1.o
mytool2.o 當倚賴的對象在目標修改後修改的話,就要去執行規則一行所指定的命
令.就象我們的上面那個Makefile第三行所說的一樣要執行 gcc -o main main.o
mytool1.o mytool2.o 注意規則一行中的TAB表示那裡是一個TAB鍵
Makefile有三個非常有用的變數.分別是$@,$^,$<代表的意義分別是:
$@--目標文件,$^--所有的依賴文件,$<--第一個依賴文件.
如果我們使用上面三個變數,那麼我們可以簡化我們的Makefile文件為:
# 這是簡化後的Makefile
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o:main.c mytool1.h mytool2.h
gcc -c $<
mytool1.o:mytool1.c mytool1.h
gcc -c $<
mytool2.o:mytool2.c mytool2.h
gcc -c $<
經過簡化後我們的Makefile是簡單了一點,不過人們有時候還想簡單一點.這里
我們學習一個Makefile的預設規則
.c.o:
gcc -c $<
這個規則表示所有的 .o文件都是依賴與相應的.c文件的.例如mytool.o依賴於
mytool.c這樣Makefile還可以變為:
# 這是再一次簡化後的Makefile
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
.c.o:
gcc -c $<
好了,我們的Makefile 也差不多了,如果想知道更多的關於Makefile規則可以查
看相應的文檔.
3.程序庫的鏈接
試著編譯下面這個程序
#include
int main(int argc,char **argv)
{
double value;
printf("Value:%f\n",value);
}
這個程序相當簡單,但是當我們用 gcc -o temp temp.c 編譯時會出現下面所示
的錯誤.
/tmp/cc33Ky.o: In function `main':
/tmp/cc33Ky.o(.text+0xe): undefined reference to `log'
collect2: ld returned 1 exit status
出現這個錯誤是因為編譯器找不到log的具體實現.雖然我們包括了正確的頭
文件,但是我們在編譯的時候還是要連接確定的庫.在Linux下,為了使用數學函數,我
們必須和數學庫連接,為此我們要加入 -lm 選項. gcc -o temp temp.c -lm這樣才能夠
正確的編譯.也許有人要問,前面我們用printf函數的時候怎麼沒有連接庫呢?是這樣
的,對於一些常用的函數的實現,gcc編譯器會自動去連接一些常用庫,這樣我們就沒
有必要自己去指定了. 有時候我們在編譯程序的時候還要指定庫的路徑,這個時候
我們要用到編譯器的 -L選項指定路徑.比如說我們有一個庫在 /home/hoyt/mylib下
,這樣我們編譯的時候還要加上 -L/home/hoyt/mylib.對於一些標准庫來說,我們沒
有必要指出路徑.只要它們在起預設庫的路徑下就可以了.系統的預設庫的路徑/lib
/usr/lib /usr/local/lib 在這三個路徑下面的庫,我們可以不指定路徑.
還有一個問題,有時候我們使用了某個函數,但是我們不知道庫的名字,這個時
候怎麼辦呢?很抱歉,對於這個問題我也不知道答案,我只有一個傻辦法.首先,我到
標准庫路徑下面去找看看有沒有和我用的函數相關的庫,我就這樣找到了線程
(thread)函數的庫文件(libpthread.a). 當然,如果找不到,只有一個笨方法.比如我要找
sin這個函數所在的庫. 就只好用 nm -o /lib/*.so|grep sin>~/sin 命令,然後看~/sin
文件,到那裡面去找了. 在sin文件當中,我會找到這樣的一行libm-2.1.2.so:00009fa0
W sin 這樣我就知道了sin在 libm-2.1.2.so庫裡面,我用 -lm選項就可以了(去掉前面
的lib和後面的版本標志,就剩下m了所以是 -lm).
4.程序的調試
我們編寫的程序不太可能一次性就會成功的,在我們的程序當中,會出現許許
多多我們想不到的錯誤,這個時候我們就要對我們的程序進行調試了.
最常用的調試軟體是gdb.如果你想在圖形界面下調試程序,那麼你現在可以選
擇xxgdb.記得要在編譯的時候加入 -g選項.關於gdb的使用可以看gdb的幫助文件.由
於我沒有用過這個軟體,所以我也不能夠說出如何使用. 不過我不喜歡用gdb.跟蹤
一個程序是很煩的事情,我一般用在程序當中輸出中間變數的值來調試程序的.當
然你可以選擇自己的辦法,沒有必要去學別人的.現在有了許多IDE環境,裡面已經自
己帶了調試器了.你可以選擇幾個試一試找出自己喜歡的一個用.
5.頭文件和系統求助
有時候我們只知道一個函數的大概形式,不記得確切的表達式,或者是不記得函數在那個頭文件進行了說明.這個時候我們可以求助系統,比如說我們想知道fread這個函數的確切形式,我們只要執行 man fread 系統就會輸出著函數的詳細解釋的.和這個函數所在的頭文件說明了。如果我們要write這個函數說明,當我們執行man write時,輸出的結果卻不是我們所需要的。因為我們要的是write這個函數的說明,可是出來的卻是write這個命令的說明。為了得到write的函數說明我們要用man 2 write。2表示我們用的是write這個函數是系統調用函數,還有一個我們常用的是3表示函數是c的庫函數。