C++ 堆栈空间不足错误(堆栈溢出错误)
我试图计算一个大小为N(平方矩阵)的矩阵乘法,但我得到了一个堆栈溢出错误(我是Cuda新手): 如果我在N<300时测试代码,一切正常,但如果在N>300时测试代码,则代码不起作用,显示堆栈溢出错误,但图形卡GF 820M中有足够的内存。 如果N=300,则300*300*4(浮点大小)=360000字节:设备中为浮点类型数组分配的必要空间。这里必须为3个表分配乘法。因此,360000*3=1080000字节,如果我控制CudaMalloc,则不显示任何内容 我告诉你,我的主要目标是测试足够大的N。我如何解决这个问题?提前感谢您可能提供的任何帮助C++ 堆栈空间不足错误(堆栈溢出错误),c++,cuda,C++,Cuda,我试图计算一个大小为N(平方矩阵)的矩阵乘法,但我得到了一个堆栈溢出错误(我是Cuda新手): 如果我在N300时测试代码,则代码不起作用,显示堆栈溢出错误,但图形卡GF 820M中有足够的内存。 如果N=300,则300*300*4(浮点大小)=360000字节:设备中为浮点类型数组分配的必要空间。这里必须为3个表分配乘法。因此,360000*3=1080000字节,如果我控制CudaMalloc,则不显示任何内容 我告诉你,我的主要目标是测试足够大的N。我如何解决这个问题?提前感谢您可能提供
#include <stdio.h>
#include<device_launch_parameters.h>
#include<cuda.h>
#include<time.h>
#include<cuda_runtime.h>
#include <math.h>
__global__ void MatrixMul( float *Md , float *Nd , float *Pd , const int WIDTH )
{ // calculate thread id
unsigned int row = blockIdx.y*blockDim.y+threadIdx.y;
unsigned int col = blockIdx.x*blockDim.x+threadIdx.x;
for (int k = 0 ; k<WIDTH ; k++ )
{ Pd[row*WIDTH + col]+= Md[row * WIDTH + k ] * Nd[ k * WIDTH + col] ; }}
int main ()
{ const int i=64 ;
cudaEvent_t start, stop;
float time;
cudaEventCreate(&start);
cudaEventCreate(&stop);
const int WIDTH =300;
cudaError_t cudaStatus;
float array1_h[WIDTH][WIDTH] ,array2_h[WIDTH][WIDTH] ,M_result_array_h[WIDTH][WIDTH];
float *array1_d , *array2_d ,*M_result_array_d ; // device array
// Allocate GPU buffers for 2 vectors (two input, one output)
cudaStatus = cudaMalloc((void **) &array1_d , WIDTH*WIDTH*sizeof (float));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!"); }
cudaStatus = cudaMalloc((void **) &array2_d , WIDTH*WIDTH*sizeof (float));
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!"); }
for ( int i = 0 ; i<WIDTH ; i++ ) {
for (int j = 0 ; j<WIDTH ; j++ )
{ array1_h[i][j] = 1 ; array2_h[i][j] = 2 ; }}
//copy host array to device array; cudaMemcpy ( dest , source , WIDTH , direction )
cudaMemcpy ( array1_d , array1_h , WIDTH*WIDTH*sizeof (float) , cudaMemcpyHostToDevice ) ;
cudaMemcpy ( array2_d , array2_h , WIDTH*WIDTH*sizeof (float) , cudaMemcpyHostToDevice ) ;
//allocating memory for resultent device array
cudaStatus = cudaMalloc((void **) &M_result_array_d , WIDTH*WIDTH*sizeof (float) ) ;
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "cudaMalloc failed!"); }
//calling kernal
dim3 dimBlock( i,i, 1 ) ;
dim3 dimGrid ( ((WIDTH-1)/i) +1 , ((WIDTH-1)/i)+1 ,1 ) ;
cudaEventRecord(start, 0);
MatrixMul <<<dimGrid,dimBlock>>> ( array1_d , array2_d ,M_result_array_d , WIDTH) ;
cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&time, start, stop);
printf ("taille du probleme:%d Time for the kernel: %f \n",WIDTH,time);
//copy back result_array_d to result_array_h
cudaMemcpy(M_result_array_h , M_result_array_d , WIDTH*WIDTH*sizeof(float) , cudaMemcpyDeviceToHost) ;
//printf the result array
for (int i = 0 ; i<WIDTH ; i++ )
{ for (int j = 0 ; j < WIDTH ; j++ )
{ printf ("%f ",M_result_array_h[i][j] ) ; }
printf ("\n") ; }
cudaFree(array1_d);
cudaFree(array2_d);
cudaFree(M_result_array_h);
system("pause") ; }
#包括
#包括
#包括
#包括
#包括
#包括
__全局无效矩阵MUL(浮点*Md、浮点*Nd、浮点*Pd、常量整数宽度)
{//计算线程id
unsigned int row=blockIdx.y*blockDim.y+threadIdx.y;
unsigned int col=blockIdx.x*blockDim.x+threadIdx.x;
对于(int k=0;k使用rtContextGetStackSize/rtContextSetStackSize找出堆栈的大小,并根据需要将其设置得更大。
请记住,图形卡上的内存与其他图形进程共享,不能全部使用
此外,您可以对矩阵进行分区,并使用逐块算法(而不是整个矩阵)计算a
堆栈溢出问题与CUDA无关。这些分配:
float array1_h[WIDTH][WIDTH] ,array2_h[WIDTH][WIDTH] ,M_result_array_h[WIDTH][WIDTH];
由编译器在堆栈上创建。堆栈空间有限。(这是主机代码,因此这里的堆栈与GPU无关。)
解决这一问题的一种可能方法是为这些变量创建动态分配,这将在堆上进行,堆没有与堆栈相同的限制
因此,一个可能的解决方案是替换此:
float array1_h[WIDTH][WIDTH] ,array2_h[WIDTH][WIDTH] ,M_result_array_h[WIDTH][WIDTH];
为此:
typedef float ar_type[WIDTH];
ar_type *array1_h, *array2_h, *M_result_array_h;
array1_h = (ar_type *)malloc(WIDTH*WIDTH*sizeof(float));
array2_h = (ar_type *)malloc(WIDTH*WIDTH*sizeof(float));
M_result_array_h = (ar_type *)malloc(WIDTH*WIDTH*sizeof(float));
还请注意:
const int i=64 ;
...
dim3 dimBlock( i,i, 1 ) ;
无效。您正在请求64x64线程块(总共4096个线程),这对于任何CUDA GPU都是不合法的。您可以通过将i
更改为32来解决此特定问题
修复后,您的内核似乎没有线程检查来防止越界线程执行和生成越界访问。您可以通过在内核for循环之前添加此线程检查来修复此问题:
if ((row < WIDTH) && (col < WIDTH))
我想你的意思是:
cudaFree(M_result_array_d);
如果您添加到代码中,和/或使用cuda memcheck
运行代码,您可以发现这些其他错误(2-4)。对于这样一个简单的程序,您可以将矩阵定义为全局矩阵,这样它们就不会在堆栈上定义。非常感谢我更正代码一切都很顺利
cudaFree(M_result_array_d);