我有一個簡單的CUDA內核,我認爲它有效地訪問全局內存。然而,Nvidia profiler報告說我正在執行低效的全局內存訪問。我的內核代碼是:CUDA探查器報告全局內存訪問效率低下
__global__ void update_particles_kernel
(
float4 *pos,
float4 *vel,
float4 *acc,
float dt,
int numParticles
)
{
int index = threadIdx.x + blockIdx.x * blockDim.x;
int offset = 0;
while(index + offset < numParticles)
{
vel[index + offset].x += dt*acc[index + offset].x; // line 247
vel[index + offset].y += dt*acc[index + offset].y;
vel[index + offset].z += dt*acc[index + offset].z;
pos[index + offset].x += dt*vel[index + offset].x; // line 251
pos[index + offset].y += dt*vel[index + offset].y;
pos[index + offset].z += dt*vel[index + offset].z;
offset += blockDim.x * gridDim.x;
}
特別剖析報告如下:
從CUDA best practices guide它說:
「對於計算能力2.x的設備的,這些需求可以很容易地總結出來:一個warp線程的併發訪問將會合併成許多事務處理,這個事務處理的數量等同於服務所有經線。默認情況下,所有訪問都通過L1緩存,即128字節的行。對於分散訪問模式,爲了減少過度訪問,有時僅在L2中進行高速緩存是有用的,L2緩存了較短的32字節段(請參閱CUDA C編程指南)。
對於計算能力3.x的設備,對全局存儲器的訪問僅緩存在L2中; L1保留用於本地內存訪問。一些計算能力爲3.5,3.7或5.2的設備也允許在L1中選擇性地緩存全局變量。「
現在在我的內核的基礎上,我期望16個訪問需要服務一個32線程扭曲,因爲float4是16字節,並且在我的卡上(770米計算能力3.0)從L2緩存中讀取是以32字節塊(16字節* 32線程/ 32字節緩存線= 16訪問)執行的。 profiler報告我正在訪問16個數據,但我不明白的是,爲什麼profiler報告理想的訪問將涉及247行的每次訪問8個L2事務,其餘行的每次訪問只有4個L2事務。我在這裏失蹤了嗎?
「每個^標記之間的差距表示探查器指出的訪問模式效率低下(無論在下一行代碼中,是否存儲到.y位置)」。謝謝。這是我錯過的關鍵信息。我重新運行你的解決方案,現在沒有任何問題! =) – James