__constant__聲明內存爲常量內存
使用常量內存可以提升運算性能的原因如下:
- 對常量內存的單次讀操作可以廣播到其他的“鄰近(nearby)”線程,這將節約15次讀取操作;
- 高速緩存。常量內存的數據將緩存起來,因此對於相同地址的連續操作將不會產生額外的內存通信量;
在CUDA架構中,線程束是指一個包含32個線程的集合,這個線程集合被“編織在一起”並且以“步調一致(Lockstep)”的形式執行。
當處理常量內存時,NVIDIA硬件將把單次內存讀取操作廣播到每個半線程束(Half-Warp)。在半線程束中包含16個線程,即線程束中線程數量的一半。如果在半線程束中的每個線程從常量內存的相同地址上讀取數據,那麼GPU只會產生一次讀取請求並在隨後將數據廣播到每個線程。如果從常量內存中讀取大量數據,那麼這種方式產生的內存流量只是使用全局內存時的1/16。
常量內存的拷貝必須用cudaMemcpyToSymbol,如下
cudaGetSymbolAddress()用來獲得__constant__內存的全局物理地址;
cudaGetSymbolSize()可以獲得__constant__內存大小
float *dp = NULL;
cudaGetSymbolAddress((void**)&dp,devData);
cudaMemcpy(dp,&value,sizeof(float),cudaMemcpyHostToDevice);
// invoke the kernel
checkGlobalVariable<<<1, 1>>>();
// copy the global variable back to the host
CHECK(cudaMemcpyFromSymbol(&value, devData, sizeof(float)));
printf("Host: the value changed by the kernel to %f\n", value);