2016-10-06 39 views
0

我想了解一个块中的线程数量如何影响cuda程序的性能和速度。我写了一个简单的载体附加码,这里是我的代码:试图找出块大小对cuda程序速度的影响

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } 
inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true) 
{ 
    if (code != cudaSuccess) 
    { 
     fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); 
     if (abort) exit(code); 
    } 
} 
__global__ void gpuVecAdd(float *a, float *b, float *c, int n) { 
    int id = blockIdx.x * blockDim.x + threadIdx.x; 
    if (id < n) { 
     c[id] = a[id] + b[id]; 
    } 
} 
int main() { 
    int n = 1000000; 
    float *h_a, *h_b, *h_c, *t; 
    srand(time(NULL)); 
    size_t bytes = n* sizeof(float); 
    h_a = (float*) malloc(bytes); 
    h_b = (float*) malloc(bytes); 
    h_c = (float*) malloc(bytes); 
    for (int i=0; i<n; i++) 
     { 
     h_a[i] =rand()%10; 
      h_b[i] =rand()%10; 
     } 
    float *d_a, *d_b, *d_c; 
    cudaMalloc(&d_a, bytes); 
    cudaMalloc(&d_b, bytes); 
    cudaMalloc(&d_c, bytes); 

    gpuErrchk(cudaMemcpy(d_a, h_a, bytes, cudaMemcpyHostToDevice)); 
    gpuErrchk(cudaMemcpy(d_b, h_b, bytes, cudaMemcpyHostToDevice)); 

    clock_t t1,t2; 
    t1 = clock(); 
    int block_size = 1024; 
    gpuVecAdd<<<ceil(float(n/block_size)),block_size>>>(d_a, d_b, d_c, n); 
    gpuErrchk(cudaPeekAtLastError()); 
    t2 = clock(); 
    cout<<(float)(t2-t1)/CLOCKS_PER_SEC<<" seconds"; 
    gpuErrchk(cudaMemcpy(h_c, d_c, bytes, cudaMemcpyDeviceToHost)); 
cudaFree(d_a); 
    cudaFree(d_b); 
    cudaFree(d_c); 
    free(h_a); 
    free(h_b); 
    free(h_c); 
} 

我读this post以及基于talonmies'答案“每个块的线程数量应为warp大小的圆形多,这是32在所有当前硬件上。

我检查了每个块的线程数不同的代码,例如2和1024(这是32的倍数,也是每块的最大线程数)。两种尺寸的平均运行时间几乎相等,我没有看到它们之间的巨大差异。这是为什么?我的基准测试是否不正确?

+1

您只是计时启动开销。你实际上并没有计算内核的持续时间。在'cudaPeekAtLastError'调用之后,向'cudaDeviceSynchronize()'添加一个调用,这将迫使你的时间内出现完整的内核持续时间。 –

+0

@RobertCrovella是的!这是问题所在。请写下您的答案,以便将其标记为正确的答案。 – starrr

回答

1

GPU内核在CUDA中启动的是异步。这意味着在内核完成执行之前,控制权将返回到CPU线程。

如果我们想让CPU线程计算内核的持续时间,我们必须让CPU线程等待,直到内核完成。我们可以通过拨打电话cudaDeviceSynchronize()进入时间区域。然后测量的时间将包括内核执行的整个持续时间。

相关问题