启动大内核大小时出现未知错误

时间:2014-03-28 22:50:58

标签: c++ cuda

当我的数组大小大于591乘591时启动一个简单的内核时遇到问题。在591x591的大小下,返回的数组没有任何错误,但是一旦启动内核网格尺寸为38x38块,每个块有16x16个线程,内核无法启动并返回“未知错误”。

以下代码是我调用的内核以及我的代码中对内核的调用:

#include <cuda.h>
#include <cuda_runtime.h>
#include <cuda_device_runtime_api.h>

using namespace std;

#define BLOCKSIZE 16
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__,__LINE__);}

inline void gpuAssert(cudaError_t code, 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 IdentityMatrixKernel(float* identity, int size)
{
int index_x = blockIdx.x * blockDim.x + threadIdx.x;
int index_y = blockIdx.y * blockDim.y + threadIdx.y;

// map the two 2D indices to a single linear, 1D index
int grid_width = gridDim.x * blockDim.x;
int index = index_y * grid_width + index_x;

// map the two 2D block indices to a single linear, 1D block index
//int result = blockIdx.y * gridDim.x + blockIdx.x;


if (index % (size+1))
{
    identity[index] = 0;
}
else
{
    identity[index] = 1;
}


void foo(float *aArray, int size)
{
float* d_I;
int size2 = size*size*sizeof(float);

gpuErrchk(cudaMalloc(&d_I,size2));

dim3 block_size;
block_size.x = BLOCKSIZE;
block_size.y = BLOCKSIZE;

dim3 grid_size;
grid_size.x = size1/ block_size.x + 1;
grid_size.y = size1/ block_size.y + 1;

IdentityMatrixKernel<<<grid_size,block_size>>>(d_I,size);
gpuErrchk(cudaPeekAtLastError());

gpuErrchk(cudaMemcpy(aArray,d_I,size2,cudaMemcpyDeviceToHost));

cudaFree(d_I);
}

int main()
{
int size = 591;
float *aArray = (float*)malloc(size*size*sizeof(float));

foo(aArray,size);


return 0;
}

对于size = 591没有出现错误,输出大小为591x591的单位矩阵,但对于任何较大的大小,它会向控制台发出“未知错误”。

2 个答案:

答案 0 :(得分:0)

一个问题似乎是您正在启动一个比实际矩阵更大的线程网格:

grid_size.x = size1/ block_size.x + 1;
grid_size.y = size1/ block_size.y + 1;

但是你没有检查内核中的任何越界访问。您需要添加一个线程检查,例如:

if ((index_x >= size)||(index_y >= size)) return;

靠近内核的开头。但这还不够。另一个问题是您的index计算不正确:

int index = index_y * grid_width + index_x;

从表面上看,它似乎是正确的,但由于你的线程数组比你的数据数组(可能)大,这可能会给出错误的索引。既然您已经将size传递给内核,请将其更改为以下内容:

int index = index_y * size + index_x;

你应该能够消除越界访问。

答案 1 :(得分:0)

我延伸了Robert Crovella的答案。

如果使用较大的数字(在您的情况下为16)定义block_size。{x,y},则您将无法使用较小尺寸的数组,例如4×4。你可以做的是定义一个小块大小:

/* create thread blocks */
dim3 block_size;
block_size.x = 4;
block_size.y = 4;

/* create n x n block grids */
dim3 grid_size;
grid_size.x = size1/block_size.x;
grid_size.y = size1/block_size.y;

/* in case of partial sizes make grid_size 1 x 1 */
if (size1 % block_size.x)
    grid_size.x = 1, grid_size.y = 1;