CUDA程序中的性能受到影响,在for循环中重复调用内核

时间:2012-01-05 15:37:42

标签: for-loop cuda gpu dynamic-programming

我有一个CUDA程序,它在for循环中重复调用内核。该 code使用前一个计算的值计算矩阵的所有行 直到整个矩阵完成。这基本上是一种动态编程算法。 下面的代码与许多单独的矩阵并行填充(i,j)条目 内核。

for(i = 1; i <=xdim; i++){

  for(j = 1; j <= ydim; j++){ 

    start3time = clock();
    assign5<<<BLOCKS, THREADS>>>(Z, i, j, x, y, z)
    end3time = clock(); 
    diff = static_cast<double>(end3time-start3time)/(CLOCKS_PER_SEC / 1000); 
    printf("Time for i=%d j=%d is %f\n", i, j, diff); 
  }

}

内核assign5很简单

__global__ void assign5(float* Z, int i, int j, int x, int y, int z) {

  int id = threadIdx.x + blockIdx.x * blockDim.x;

  char ch = database[j + id];

  Z[i+id] = (Z[x+id] + Z[y+id] + Z[z+id])*dev_matrix[i][index[ch - 'A']];

  }

}

我的问题是,当我运行这个程序时,每个i和j的时间大多为0 时间,但有时它是10毫秒。所以输出看起来像

Time for i=0 j=0 is 0
Time for i=0 j=1 is 0
.
.
Time for i=15 j=21 is 10
Time for i=15 j=22 is 0
.

我不明白为什么会这样。我没有看到线程竞争条件。如果我添加

if(i % 20 == 0) cudaThreadSynchronize();

在第一个循环之后,然后i和j的时间大多为0.但是时间 同步有时是10甚至20。看起来CUDA正在执行许多操作 以低成本,然后为后来的收费很多。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:6)

我认为您对CUDA中的内核调用在主机上实际执行的操作存在误解。内核调用是非阻塞的,只会添加到设备的队列中。如果你在内核调用之前和之后测量时间,那么差异与内核调用花费的时间无关(它将测量将内核调用添加到队列所花费的时间)。

您应该在每次内核调用之后和测量end3time之前添加cudaThreadSynchronize()。如果队列中的所有内核都已完成其工作,cudaThreadSynchronize()将阻塞并返回。

这就是为什么

if(i % 20 == 0) cudaThreadSynchronize();

在你的测量中出现了高峰。