我的问题是,当程序首次进入main时,我在程序启动时收到堆栈溢出异常。我的程序是使用CUDA的并行蒙特卡罗Pi计算器。当我尝试在Visual Studio中调试程序时,在我可以选择的任何断点之前会弹出异常。任何帮助表示赞赏。
#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;
}
答案 0 :(得分:1)
您要声明共享内存的大小=大小;喜欢这里
monteCarlo <<<dimGrid, dimBlock, size>>>
size = 512 * 65534 * 4 = 2 ^ 9 * 2 ^ 16 * 2 ^ 2 = 2 ^ 27(超过我能想到的任何卡上共享内存的最大值)。
但是看看你的内核,我想你希望共享内存等于你拥有的线程数。
所以你要么做
1)
这用于启动你的内核
monteCarlo <<<dimGrid, dimBlock, (NUM_THREADS * sizeof(int))>>>
2)
或者使用它来启动内核
monteCarlo <<<dimGrid, dimBlock>>>
这是在你的内核中声明你的共享内存。
__shared__ int sdata[NUM_THREADS]; // Note: no extern before __shared__
我个人更喜欢这两种内核的方法二,因为共享内存与线程数成正比,但已知线程数是常量。它也稍快一些。
修改强>
除了上述问题外,我怀疑这可能会导致问题。
cudaMalloc((void **) &devStates, size*sizeof(curandState));
因为这个本身就是这个。
size = NUM_BLOCKS * NUM_THREADS * sizeof(float);
可能你想这样做吗?
cudaMalloc((void **) &devStates, (NUM_BLOCKS *NUM_THREADS)*sizeof(curandState));
至于实际的堆栈溢出问题,您可能需要查看talonmies post。
答案 1 :(得分:1)
我认为问题是:
float *sumDev, sumHost[NUM_BLOCK*NUM_THREAD];
代表
#define NUM_THREAD 512
#define NUM_BLOCK 65534
这将为您留下大约130Mb的静态声明数组。我怀疑编译器运行时库可以处理如此大的静态分配,这就是你得到即时堆栈溢出的原因。用动态分配替换它,堆栈溢出问题就会消失。但仔细阅读Pavan's post,因为一旦你修复了堆栈溢出,CUDA代码本身也需要重新设计才能生效。