CUDA編程的學(xué)習(xí),需要熟練的掌握C/C++編程的基礎(chǔ)及操作系統(tǒng)方面的知識(shí)。
只有主機(jī)代碼的cuda程序在cuda程序中,既有純粹的c++代碼,又有不屬于c++代碼的真正的cuda代碼。cuda程序的編譯器為nvcc,在編譯一個(gè)cuda程序時(shí),純粹的c++代碼使用g++等編譯器編譯,剩下的就由nvcc負(fù)責(zé)編譯。cuda的程序一般命名為xxx.cu
#includeint main()
{printf("hello world!\n");
return 0;
}
和c++的編譯指令類似:-g表示可以debug
nvcc -g hello.cu -o hello
前面使用主機(jī)的cuda程序,雖然使用cuda編譯,但是并沒有使用GPU。GPU只是一個(gè)設(shè)備,要它工作的話,需要主機(jī)(一般是CPU)給它下達(dá)指令。一個(gè)利用GPU的cuda程序既要有主機(jī)代碼,也要有設(shè)備代碼。主機(jī)對(duì)設(shè)備的調(diào)用是通過核函數(shù)來(lái)實(shí)現(xiàn)。
主要結(jié)構(gòu)的形式:
int main()
{主機(jī)代碼
核函數(shù)的調(diào)用
主機(jī)代碼
return 0;
}
cuda里的核函數(shù)核函數(shù)存在一些要求(大部分在之后都會(huì)有例子說明):
__global__ void hello_from_gpu()
{printf("hello world from the gpu!\n");
}
void __global__ hello_from_gpu()
{printf("hello world from the gpu!\n");
}
一個(gè)GPU中有很多計(jì)算核心,可以支持很多線程。設(shè)備在調(diào)用核函數(shù)時(shí)要明確使用多少個(gè)線程。
hello_from_gpu<<<1,1>>>(); // 設(shè)備只使用一個(gè)線程
(3)核函數(shù)的調(diào)用:要有<<<>>>,用這個(gè)來(lái)指明設(shè)備中要指派多少個(gè)線程。其中<<<網(wǎng)格大小,線程塊大小>>>。網(wǎng)格大?。嚎梢钥醋魇蔷€程塊的個(gè)數(shù)。線程塊大?。嚎梢钥醋魇敲總€(gè)線程塊包含的線程數(shù)量。核函數(shù)中總的線程數(shù)等于網(wǎng)格大小乘以線程塊大小。
(4) 函數(shù)名無(wú)特殊要求,支持C++中的重載。
(5) 核函數(shù)不支持可變數(shù)量的參數(shù)列表,參數(shù)的個(gè)數(shù)必須確定。
(6) 除非使用統(tǒng)一的內(nèi)存編程機(jī)制,否則傳給核函數(shù)的參數(shù)有數(shù)組或指針類型時(shí),必須是指向設(shè)備的內(nèi)存。
(7) 核函數(shù)不能成為一個(gè)類的成員。通常的做法是用一個(gè)包裝函數(shù)調(diào)用核函數(shù),而將包裝函數(shù)定義為類的成員。
(8) 在GPU的計(jì)算能力3.5之前核函數(shù)之間不能相互調(diào)用,3.5之后引入動(dòng)態(tài)并行機(jī)制后,可以相互調(diào)用了,甚至可以遞歸。
cudaDeviceSynchronize():cuda運(yùn)行時(shí)的API函數(shù),作用是同步主機(jī)與設(shè)備,因?yàn)楹撕瘮?shù)的調(diào)用是異步的,主機(jī)發(fā)出調(diào)用核函數(shù)指令后不等待核函數(shù)執(zhí)行完畢會(huì)立即執(zhí)行程序后面的語(yǔ)句。
使用和函數(shù)的cuda程序:
#include__global__ void hello_from_gpu()
{printf("hello world from the gpu!\n");
}
int main()
{hello_from_gpu<<<1,1>>>();
cudaDeviceSynchronize();
return 0;
}
cuda中的線程組織
多個(gè)線程的核函數(shù)和函數(shù)代碼執(zhí)行的指令是“單指令-多線程”,即每一個(gè)線程都執(zhí)行同一串指令。如下代碼,會(huì)打印出8行同樣的文字
#include__global__ void hello_from_gpu()
{printf("hello world from the gpu!\n");
}
int main()
{hello_from_gpu<<<2,4>>>();
cudaDeviceSynchronize();
return 0;
}
每個(gè)線程在核函數(shù)中都有一個(gè)唯一的身份標(biāo)識(shí),我們可以通過線程索引來(lái)獲取到底是哪一個(gè)線程執(zhí)行的代碼。
在核函數(shù)內(nèi)部,grid_size和block_size的值保存在兩個(gè)內(nèi)建變量中。
#include__global__ void hello_from_gpu()
{const int bid = blockDim.x;
const int tid = threadIdx.x;
printf("hello world from %d block and the %d thread!\n",bid,tid);
}
int main()
{hello_from_gpu<<<2,4>>>();
cudaDeviceSynchronize();
return 0;
}
其實(shí)線程塊的(0,1)順序不一定,因?yàn)閏uda的計(jì)算特征是每個(gè)線程塊的計(jì)算是相互獨(dú)立的。
內(nèi)建變量是使用c++中的結(jié)構(gòu)體或者類定義的。
blockIdx和threadIdx是類型為unit3的變量,是一個(gè)結(jié)構(gòu)體類型,具有x,y,z這3個(gè)成員。
使用多維線程的示例:
#include__global__ void hello_from_gpu()
{const int b = blockIdx.x;
const int tx = threadIdx.x;
const int ty = threadIdx.y;
printf("hello world from %d block and the (%d,%d) thread!\n",b,tx,ty);
}
int main()
{const dim3 block_size(2,4);
hello_from_gpu<<<1,block_size>>>();
cudaDeviceSynchronize();
return 0;
}
CUDA編程是通往高性能計(jì)算的道路,學(xué)習(xí)掌握cuda編程,將其運(yùn)用在一些計(jì)算機(jī)視覺的部署任務(wù)中是十分常見和高效的。
參考:如博客內(nèi)容有侵權(quán)行為,可及時(shí)聯(lián)系刪除!
CUDA 編程:基礎(chǔ)與實(shí)踐
https://docs.nvidia.com/cuda/
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
分享文章:CUDA編程筆記(1)-創(chuàng)新互聯(lián)
URL分享:http://jinyejixie.com/article42/dedihc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、軟件開發(fā)、全網(wǎng)營(yíng)銷推廣、品牌網(wǎng)站設(shè)計(jì)、搜索引擎優(yōu)化、營(yíng)銷型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)