我正在尝试将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作为外部的。
答案 0 :(得分:4)
这里有很多错误,但是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个线程。
您的代码中可能还有其他问题。我停止了照顾,我找到了这两个。