这是一个简单的CUDA代码,用于初始化一个大矩阵(填充零)。
如果代码有效,我输出第一个1 * 3矩阵。它应该全是零。
如果我将矩阵大小设置得很小,那么程序就能正常工作。但是当我把尺寸变大(> 43200 * 2400)时,矩阵里面的东西都是垃圾。
我已经在每个CUDA函数的末尾追加了cudaDeviceSynchronize()。
我使用的是NVIDIA Quadro K4200,Xeon E5-2630和Ubuntu 14.04。
感谢有人在这里帮助我。
以下是我的完整代码。
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <cuComplex.h>
#define BLOCK_SIZE 16 // change it to 16 to get maximum performance
// populate the matrix using first row
__global__ void RepmatKernel (cuComplex *Mat, const unsigned int N, const unsigned int Cols)
{
unsigned int i = (unsigned int)blockIdx.x * (unsigned int)blockDim.x + (unsigned int)threadIdx.x;
if (i < N)
{
Mat[i].x = 0;
Mat[i].y = 0;
}
}
// main routine
int main ()
{
const unsigned int Rows = 43200;
const unsigned int Cols = 2400;
const unsigned int Num_thrd = 256; // max threads per block
unsigned int Mat_size = Rows * Cols; // size of array
cuComplex *vec; // supposedly the input
cuComplex *mat_debug; // for debug
vec = new cuComplex [Cols];
mat_debug = new cuComplex [Rows*Cols];
cuComplex *mat_in_d; // device array
//input in host array
for(unsigned int i = 0; i < Cols; i++)
{
vec[i].x = 3*i+4;
vec[i].y = 0.2*i+1;
}
const unsigned int size_mat_d = Rows * Cols * sizeof(cuComplex);
//create device array cudaMalloc ( (void **)&array_name, sizeofmatrixinbytes) ;
if (cudaMalloc((void **) &mat_in_d , size_mat_d) != cudaSuccess) std::cout<<"Error allocating GPU";
cudaDeviceSynchronize() ;
//copy host array to device array; cudaMemcpy ( dest , source , WIDTH , direction )
cudaMemcpy ( mat_in_d , vec , Cols , cudaMemcpyHostToDevice ) ;
cudaDeviceSynchronize() ;
// ========================================================================
cudaMemcpy(mat_debug , mat_in_d , size_mat_d , cudaMemcpyDeviceToHost) ;
cudaDeviceSynchronize() ;
std::cout<<"before repmat="<<std::endl;
std::cout<<"[";
for(unsigned int i = 0; i < 3; i++)
{
std::cout<< mat_debug[i * Cols].x <<"+"<<mat_debug[i * Cols].y <<"i, ";
std::cout<<";"<<std::endl;
}
std::cout<<"]"<<std::endl;
// ==========================================================================
RepmatKernel<<<(unsigned int)ceil((float)(Mat_size)/(float)(Num_thrd)),
(Num_thrd)>>>(mat_in_d,
Mat_size,
Cols);
cudaDeviceSynchronize();
// ========================================================================
cudaMemcpy(mat_debug , mat_in_d , size_mat_d , cudaMemcpyDeviceToHost) ;
cudaDeviceSynchronize() ;
std::cout<<"after repmat="<<std::endl;
std::cout<<"[";
for(unsigned int i = 0; i < 3; i++)
{
std::cout<< mat_debug[i * Cols].x <<"+"<<mat_debug[i * Cols].y <<"i, ";
std::cout<<";"<<std::endl;
}
std::cout<<"]"<<std::endl;
// ==========================================================================
cudaFree(mat_in_d);
delete [] vec;
delete [] mat_debug;
return 0;
}
答案 0 :(得分:1)
您对cudaMalloc
的调用声明存在问题,但实际上并未终止计算。你应该放一个
if (cudaMalloc((void **) &mat_in_d , size_mat_d) != cudaSuccess)
{
std::cout<<"Error allocating GPU\n";
return 1;
}
这样当你溢出内存时计算实际上就停止了,而不是只用std::cout
的警告来尝试工作。更好的方法是使用error handling macro。
另一个问题是:
cudaMemcpy ( mat_in_d , vec , Cols , cudaMemcpyHostToDevice );
首先,mat_in_d
的大小为Rows * Cols * sizeof(cuComplex)
,但您只是将Cols
个字节复制到其中。即使您只想将vec
复制到mat_in_d
向量的第一部分,您也需要将其更改为
cudaMemcpy ( mat_in_d , vec , Cols*sizeof(cuComplex) , cudaMemcpyHostToDevice );
此时,您希望矩阵的第一个Cols
条目合理,其余条件是垃圾。 (做出建议的更改表明情况确实如此;为什么你想这样做是一个更好的问题。)
接下来是内核调用,其目标是将Mat
的条目设置为零。这应该使用cudaMemset
完成,即只需使用
cudaMemset(mat_in_d, 0, Mat_size*sizeof(cuComplex));
我们可以更仔细地查看执行配置,看看你的内核调用出了什么问题,但是现在这可以解决你的问题。
答案 1 :(得分:0)
用于调试CUDA错误;我从样本helper_cuda.h
找到一个标题,非常方便。我几乎总是在我的项目中包含这个标题,它位于样本的公共目录中。
然后,使用checkCudaErrors()
包装所有CUDA调用,如checkCudaErrors(cudaMalloc((void **) &mat_in_d , size_mat_d));
,会显示错误消息。
在我的情况下,因为只有mat_in_d
接近1 GB且我的GPU的内存只有512 MB,所以它确实失败并抛出cudaErrorMemoryAllocation
。但是,NVIDIA Quadro K4200不应该那么容易失败!
您是否使用cudaMemGetInfo
检查了实际可用的内存信息?