2011-05-30 85 views
1

我的问题是,当程序第一次进入主程序时,程序启动时出现堆栈溢出异常。我的程序是使用CUDA的并行Monte Carlo Pi计算器。当我尝试在Visual Studio中调试程序时,在我可以选择任何断点之前弹出该异常。任何帮助表示赞赏。程序启动时堆栈溢出异常(CUDA Monte Carlo Pi)

#include <stdio.h> 
#include <stdlib.h> 
#include <cuda.h> 
#include <curand.h> 
#include <curand_kernel.h> 

#define NUM_THREAD 512 
#define NUM_BLOCK 65534 

/////////////////////////////////////////////////////////////////////////////////////////// 
/////////////////////////////////////////////////////////////////////////////////////////// 
// Function to sum an array 
__global__ void reduce0(float *g_odata) { 
extern __shared__ int sdata[]; 

// each thread loads one element from global to shared mem 
unsigned int tid = threadIdx.x; 
unsigned int i = blockIdx.x*blockDim.x + threadIdx.x; 
sdata[tid] = g_odata[i]; 
__syncthreads(); 

// do reduction in shared mem 
for (unsigned int s=1; s < blockDim.x; s *= 2) { // step = s x 2 
    if (tid % (2*s) == 0) { // only threadIDs divisible by the step participate 
     sdata[tid] += sdata[tid + s]; 
    } 
    __syncthreads(); 
} 

// write result for this block to global mem 
if (tid == 0) g_odata[blockIdx.x] = sdata[0]; 
} 

/////////////////////////////////////////////////////////////////////////////////////////// 
/////////////////////////////////////////////////////////////////////////////////////////// 
__global__ void monteCarlo(float *g_odata, int trials, curandState *states){ 
    extern __shared__ int sdata[]; 
// unsigned int tid = threadIdx.x; 
    unsigned int i = blockIdx.x*blockDim.x + threadIdx.x; 
    unsigned int k, incircle; 
    float x, y, z; 
    incircle = 0; 

    curand_init(1234, i, 0, &states[i]); 

    for(k = 0; k < trials; k++){ 

    x = curand_uniform(&states[i]); 
    y = curand_uniform(&states[i]); 
    z = sqrt(x*x + y*y); 
    if (z <= 1) incircle++; 
    else{} 
    } 
    __syncthreads(); 
    g_odata[i] = incircle; 
} 
/////////////////////////////////////////////////////////////////////////////////////////// 
/////////////////////////////////////////////////////////////////////////////////////////// 
int main() { 

    float* solution = (float*)calloc(100, sizeof(float)); 
    float *sumDev, sumHost[NUM_BLOCK*NUM_THREAD]; 
    int trials, total; 
    curandState *devStates; 



    trials = 100; 
    total = trials*NUM_THREAD*NUM_BLOCK; 

    dim3 dimGrid(NUM_BLOCK,1,1); // Grid dimensions 
    dim3 dimBlock(NUM_THREAD,1,1); // Block dimensions 
    size_t size = NUM_BLOCK*NUM_THREAD*sizeof(float); //Array memory size 
    cudaMalloc((void **) &sumDev, size); // Allocate array on device 
    cudaMalloc((void **) &devStates, size*sizeof(curandState)); 
    // Do calculation on device by calling CUDA kernel 
    monteCarlo <<<dimGrid, dimBlock, size>>> (sumDev, trials, devStates); 
     // call reduction function to sum 
    reduce0 <<<dimGrid, dimBlock, size>>> (sumDev); 
    // Retrieve result from device and store it in host array 
    cudaMemcpy(sumHost, sumDev, size, cudaMemcpyDeviceToHost); 

    *solution = 4*(sumHost[0]/total); 
    printf("%.*f\n", 1000, *solution); 
    free (solution); 
    //*solution = NULL; 
    return 0; 
} 

回答

1

我认为问题是这样的:

float *sumDev, sumHost[NUM_BLOCK*NUM_THREAD]; 

#define NUM_THREAD 512 
#define NUM_BLOCK 65534 

这使得你一个大概130MB的静态声明数组。我怀疑编译器运行时库可以处理如此大的静态分配,这就是为什么你会得到即时堆栈溢出。将其替换为动态分配,并且堆栈溢出问题将消失。但仔细阅读Pavan's post,因为一旦你修复了堆栈溢出问题,CUDA代码本身在工作之前也需要重新设计。

+0

啊,是的,这是造成这个问题。 Pavan的帖子也帮助我重新设计了我的CUDA代码。谢谢 – zetatr 2011-05-31 00:10:11

1

您正在声明shared memory = size的大小;像这里

monteCarlo <<<dimGrid, dimBlock, size>>> 

大小的值= 512 * 65534 * 4 = 2^9 * 2^16 * 2^2 = 2^27(超过共享存储器的任何卡上的最大值I能想到的)。

但看着你的内核,我认为你想让共享内存等于你拥有的线程数。

所以,你要么需要做

1)
这对于启动您的内核

monteCarlo <<<dimGrid, dimBlock, (NUM_THREADS * sizeof(int))>>> 

2)
或者用这个启动您的内核

monteCarlo <<<dimGrid, dimBlock>>> 

这在你的内核中声明你的共享内存。

__shared__ int sdata[NUM_THREADS]; // Note: no extern before __shared__ 

我个人偏好方法两个用于这些种核的,因为共享存储器是正比于线程的数目,但线程的数量是已知的恒定。它也稍微快一点。

编辑

除了我怀疑,这可能会导致问题太forementioned问题。

cudaMalloc((void **) &devStates, size*sizeof(curandState)); 

因为大小本身就是这样。

size = NUM_BLOCKS * NUM_THREADS * sizeof(float); 

可能是你想这样做呢?

cudaMalloc((void **) &devStates, (NUM_BLOCKS *NUM_THREADS)*sizeof(curandState)); 

至于实际的堆栈溢出问题,你可能要看看talonmies post

+0

我怀疑这是初始堆栈溢出的来源 – talonmies 2011-05-30 04:52:58

+0

是的,你说得对。不太熟悉幕后。我只是针对我发现的明显问题提出了解决方案。感谢您澄清您的帖子中的内容。 – 2011-05-30 05:17:02