【发布时间】:2015-11-06 06:43:48
【问题描述】:
我不是经验丰富的 CUDA 程序员。我遇到了这样的问题。 我正在尝试将一个大矩阵 (10K*10K) 的瓦片 (32x32) 从全局内存加载到共享内存中,并在它发生时对其进行计时。我意识到如果我将它加载到私有内存(寄存器),它的加载速度比共享内存加载快 4-5 倍。
__global__ void speedtest( float *vel,int nx) {
int globalx = blockDim.x * blockIdx.x + threadIdx.x+pad;
int globalz = blockDim.y * blockIdx.y + threadIdx.y+pad;
int localx=threadIdx.x;
int localz=threadIdx.y;
float ptest;
__shared__ float stest[tile][tile];
//stest[localz][localx]=vel[globalz*nx+globalx]; //load to shared memory
ptest=vel[globalz*nx+globalx]; //load to private memory
__syncthreads();
}
我将stest和ptest一一注释掉,用cudaeventrecord计算经过的时间。 stest 用了 3.2 毫秒,ptest 用了 0.75 毫秒来加载。我究竟做错了什么?时间应该非常相似吧?我错过了什么?
配置:Cuda 7.5,gtx 980,只有32bit变量和计算,没有具体用途,我只是在玩。
我正在按要求发布示例代码
#include<stdio.h>
#include <math.h>
#define tile 32
#include <helper_cuda.h>
void makeittwo(float *array,int nz,int nx)
{
//this just assigns a number into the vector
int n2;
n2=nx*nz;
for (int i=0;i<n2;i++)
array[i]=2000;
}
__global__ void speedtest( float *vel,int nx,int nz) {
int globalx = blockDim.x * blockIdx.x + threadIdx.x;
int globalz = blockDim.y * blockIdx.y + threadIdx.y;
int localx=threadIdx.x;
int localz=threadIdx.y;
float ptest; //declarations
__shared__ float stest[tile][tile];
if (globalx<nx && globalz<nz){
stest[localz][localx]=vel[globalz*nx+globalx]; //shared variable
//ptest=vel[globalz*nx+globalx]; //private variable
//comment out ptest and stest one by one to test them
}
__syncthreads();
}
int main(int argc,char *argv)
{
int nx,nz,N;
float *vel;
nz=10000;nx=10000; //matrix dimensions
N=nz*nx; //convert matrix into vector
checkCudaErrors(cudaMallocHost(&vel,sizeof(float)*N)); //using pinned memory
makeittwo(vel,nz,nx);
dim3 dimBlock(tile,tile);
dim3 dimGrid;
int blockx=dimBlock.x;
int blockz=dimBlock.y;
dimGrid.x = (nx + blockx - 1) / (blockx);
dimGrid.y = (nz + blockz - 1) / (blockz);
float *d_vel;
checkCudaErrors(cudaMalloc(&d_vel,sizeof(float)*(N))); //copying to device
checkCudaErrors(cudaMemcpy(d_vel, vel, sizeof(float)*(N), cudaMemcpyHostToDevice));
cudaEvent_t start,stop;
float elapsedTime;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start,0);
speedtest<<<dimGrid,dimBlock>>>(d_vel,nx,nz); //calling the function
cudaEventRecord(stop,0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&elapsedTime,start,stop);
printf("time=%3.3f ms\n",elapsedTime);
checkCudaErrors(cudaMemcpy(vel, d_vel, sizeof(float)*N, cudaMemcpyDeviceToHost));
//calling the matrix back to check if all went well (this fails if out of bound calls are made)
cudaDeviceReset();
}
【问题讨论】:
-
宁可将文件内容直接包含在您的问题中,而不是链接到场外资源
-
你没有测量你期望测量的东西:在“注册代码”中,编译器完全优化了赋值。
-
ptest*=ptest不会改变任何东西。 Is 被编译器删除...一种可能性是将值存储回全局内存,如您所述。然后编译器无法删除该指令。但是,在这种情况下,您正在测量读取和写入。链接方向是什么意思? -
“后来我决定把它们写回原来的全局内存,然后时间就神奇地相等了。”正如@havogt 现在多次说过的那样,编译器正在优化您编写的代码。你可能不明白这其中的程度。不影响全局状态的代码可以被编译器删除。这种通过注释掉代码行来进行性能分析的方法可能会充满错误,尤其是对于初学者而言。 SO上的cuda标签上有很多这样的问题。
-
@havogt 如果你想提供答案,我会投票赞成。
标签: c performance cuda shared-memory