http://blog.csdn.net/bendanban/article/details/7928744
引言:
什么是基于指令的移植方式呢?首先我這里說(shuō)的移植可以理解為把原先在CPU上跑的程序放到像GPU一樣的協(xié)處理器上跑的這個(gè)過(guò)程。在英文里可以叫Porting。移植有兩種方式:一種是使用CUDA或者OpenCL來(lái)重新設(shè)計(jì)代碼,然后使用硬件廠商提供的編譯器來(lái)編譯;一種是使用OpenACC或者OpenHMPP提供的指令集添加到你想使用GPU計(jì)算的源代碼中的某個(gè)位置,讓編譯器來(lái)編譯出GPU上執(zhí)行的代碼。后一種方式就是基于指令的移植方式。
例如,下面一個(gè)簡(jiǎn)單的循環(huán):
for (i=0; i<n;i++)


{
dosomething(i);
}
如果你想把這個(gè)循環(huán)放到GPU上,讓每個(gè)線程計(jì)算一次i的話,可以這樣做:
#pragma acc kernels
for (i=0; i<n;i++)


{
dosomething(i);
}
網(wǎng)格化(gridification):
這樣,編譯器拿到加了OpenACC指令的那段代碼后,就會(huì)把你的循環(huán)放到GPU或者其他硬件加速器(例如MIC)上。編譯器分析了#pragma acc kernels下面的那個(gè)循環(huán),就會(huì)根據(jù)循環(huán)的次數(shù)來(lái)分配線程數(shù)量,這個(gè)過(guò)程就叫網(wǎng)格化。為什么說(shuō)是網(wǎng)格化呢?可以這樣理解,因?yàn)镚PU可以啟動(dòng)很多線程,這些線程就像一張漁網(wǎng)一樣,可以認(rèn)為一個(gè)網(wǎng)格代表一個(gè)線程,所以我就干脆叫這個(gè)過(guò)程為“網(wǎng)格化”了。
內(nèi)核(kernel)
在OpenACC里可以這樣理解內(nèi)核:內(nèi)核就是在協(xié)處理器(例如GPU)上被多個(gè)線程同時(shí)執(zhí)行的一段代碼。如果每個(gè)線程都做一個(gè)活,豈不是沒(méi)意思了么?當(dāng)然不是這樣的,他們執(zhí)行的代碼是一樣的,但是每個(gè)線程可以根據(jù)自己的ID號(hào)來(lái)針對(duì)不同的數(shù)據(jù)做同樣的工作,這也就是數(shù)據(jù)并行的含義。
codelet
使用CAPS的HMPP Workbench編譯加了OpenACC指導(dǎo)語(yǔ)句的源代碼時(shí),編譯器會(huì)告訴你codelet產(chǎn)生了。實(shí)際上產(chǎn)生了一個(gè)CUDA或者OpenCL的源文件,這個(gè)源文件中包含了根據(jù)你的指導(dǎo)語(yǔ)句生成的CUDA或者OpenCL的源代碼。那什么是codelet呢?可以認(rèn)為codelet就是數(shù)據(jù)管理+內(nèi)核。一個(gè)codelet要干的事情包括兩部分:申請(qǐng)和管理CPU和協(xié)處理器之間的存儲(chǔ),還有就是啟動(dòng)在協(xié)處理上執(zhí)行的代碼。
work-sharing
這個(gè)詞可以理解為名詞“共享工作”。如果在協(xié)處理器上的線程們執(zhí)行的工作時(shí)work-sharing的,那么每個(gè)線程可以根據(jù)自己的ID在不同的數(shù)據(jù)上干了相似的工作。這個(gè)詞是在使用OpenACC或者OpenHMPP移植代碼的時(shí)候遇到的,它描述的是CPU的串行代碼中的狀態(tài),例如:
for (i=0; i<n; i++)


{
a[i] = i;
}
在這段代碼中,a[i]的計(jì)算與a[i]之外的a的元素沒(méi)有依賴性,所以,每次循環(huán)的i可以使獨(dú)立的完成的,像這樣的狀態(tài)就是work-sharing的。還有例如規(guī)約,
s = 0;
for (i=0; i<n; i++)


{
s+=a[i];
}
雖然s的計(jì)算與i相關(guān),但是細(xì)想一下,加法在數(shù)學(xué)上市滿足交換律的,s的每次加a[i]實(shí)際上不相關(guān)的,你不管以什么順序加和a[i]到s,解結(jié)果總是一樣的。所以規(guī)約也可以理解為是worksharing 的。就說(shuō)這么多吧。如果大家有什么問(wèn)題,歡迎給我留言?shī)W。