【问题标题】:Cuda triple nested for loop assignementCuda 三重嵌套 for 循环赋值
【发布时间】:2016-06-29 10:50:07
【问题描述】:

我正在尝试将 c++ 代码转换为 Cuda 代码,并且我有以下三重嵌套 for 循环,它将填充一个数组以进行进一步的 OpenGL 渲染(我只是创建一个坐标顶点数组):

for(int z=0;z<263;z++) {                    
       for(int y=0;y<170;y++) {
           for(int x=0;x<170;x++) {
               g_vertex_buffer_data_3[i]=(float)x+0.5f;
               g_vertex_buffer_data_3[i+1]=(float)y+0.5f;
               g_vertex_buffer_data_3[i+2]=-(float)z+0.5f; 
               i+=3;            
           }
       }
   }

我想获得更快的操作,因此我将使用 Cuda 进行一些操作,例如上面列出的操作。我想为最外层循环的每次迭代创建一个块,并且由于内部循环的迭代次数为 170 * 170 = 28900 次总迭代,因此为每个最内层循环迭代分配一个线程。我将 c++ 代码转换成这个(这只是一个我为了解如何使用 Cuda 而制作的小程序):

__global__ void mykernel(int k, float *buffer) {
int idz=blockIdx.x;
int idx=threadIdx.x;
int idy=threadIdx.y;

buffer[k]=idx+0.5;
buffer[k+1]=idy+0.5;
buffer[k+2]=idz+0.5;
k+=3;

}

int main(void) {
  int dim=3*170*170*263;
  float* g_vertex_buffer_data_2 = new float[dim];
  float* g_vertex_buffer_data_3;
  int i=0;

  HANDLE_ERROR(cudaMalloc((void**)&g_vertex_buffer_data_3, sizeof(float)*dim));

  dim3 dimBlock(170, 170);

  dim3 dimGrid(263);

  mykernel<<<dimGrid, dimBlock>>>(i, g_vertex_buffer_data_3);

  HANDLE_ERROR(cudaMemcpy(&g_vertex_buffer_data_2,g_vertex_buffer_data_3,sizeof(float)*dim,cudaMemcpyDeviceToHost));

  for(int j=0;j<100;j++){
    printf("g_vertex_buffer_data_2[%d]=%f\n",j,g_vertex_buffer_data_2[j]);
  }
  cudaFree(g_vertex_buffer_data_3);

  return 0;

}

尝试启动它时出现分段错误。你知道我在做什么错吗? 我认为问题在于 threadIdx.x 和 threadIdx.y 同时增长,而我想让 threadIdx.x 成为内部的,threadIdx.y 成为外部的。

【问题讨论】:

    标签: c++ for-loop cuda nested-loops


    【解决方案1】:

    这里有很多错误,但是segfault的来源是这样的:

    cudaMemcpy(&g_vertex_buffer_data_2,g_vertex_buffer_data_3,
                    sizeof(float)*dim,cudaMemcpyDeviceToHost);
    

    你要么想要

    cudaMemcpy(&g_vertex_buffer_data_2[0],g_vertex_buffer_data_3,
                    sizeof(float)*dim,cudaMemcpyDeviceToHost);
    

    cudaMemcpy(g_vertex_buffer_data_2,g_vertex_buffer_data_3,
                    sizeof(float)*dim,cudaMemcpyDeviceToHost);
    

    一旦你修复了这个问题,你会注意到内核实际上永远不会因为无效的启动错误而启动。这是因为(170,170) 的块大小是非法的。 CUDA 在所有当前硬件上的每个块限制为 1024 个线程。

    您的代码中可能还存在其他问题。找到这两个后,我不再寻找。

    【讨论】:

    • 我编辑了第一件事,谢谢!现在我尝试第二个,我必须找到正确的方法来设置每个网格的块数和每个块的线程数。对于我的三重嵌套循环,我应该使用 threadsId 和 blockId 作为 g_vertex_buffer_data_3 的索引还是应该使用在每个循环中增加的不同索引?
    • 您可以从较小的数据集开始解决您遇到的其他问题,而不是使用如此大的数据集,例如:k+=3 没有达到您的预期,测试缓冲区溢出和g_vertex_buffer_data_2 正在泄漏。之后,您可以例如分区整个数据集并多次调用您的 CUDA 内核,以解决硬件限制。但首先要搞清楚逻辑。
    • 非常感谢!我怎么能用 CUDA 做 k+=3?我的意思是,我怎么能告诉 Cuda 在 c++ 中做 k+=3 的操作?
    • @NicolòCogno:在您的问题已经得到回答后,请不要编辑来更改它。这不是您的个人帮助线程。这是一个问题。我回答了,你现在已经变成了别的东西。这不是Stack Overflow 的工作方式。如果您有不同的问题(看起来确实如此),请提出一个新问题。,
    猜你喜欢
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-16
    • 1970-01-01
    相关资源
    最近更新 更多