1

私の問題は、プログラムが最初にメインに入ったときに、プログラムの開始時にスタック オーバーフロー例外を受け取っていることです。私のプログラムは、CUDA を使用した Parallel Monte Carlo 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;
}
4

2 に答える 2

1

共有メモリのサイズ = size; を宣言しています。ここみたいに

monteCarlo <<<dimGrid, dimBlock, 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__

共有メモリはスレッドの数に比例しますが、スレッドの数は一定であることが知られているため、私は個人的にこれらの種類のカーネルには方法 2 を好みます。また、わずかに高速です。

編集

前述の問題とは別に、これも問題を引き起こしているのではないかと思います。

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

サイズ自体はこれだから。

size = NUM_BLOCKS * NUM_THREADS * sizeof(float);

代わりにこれをやりたかったのでしょうか?

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

実際のスタック オーバーフローの問題については、talonmies の投稿を参照してください。

于 2011-05-30T03:44:52.587 に答える
1

問題はこれだと思います:

float *sumDev, sumHost[NUM_BLOCK*NUM_THREAD];

為に

#define NUM_THREAD 512
#define NUM_BLOCK 65534

これにより、約 130Mb の静的に宣言された配列が残ります。コンパイラのランタイム ライブラリがこのような大規模な静的割り当てを処理できるとは思えません。そのため、即座にスタック オーバーフローが発生します。これを動的割り当てに置き換えると、スタック オーバーフローの問題は解消されます。ただし、Pavan の投稿を注意深く読んでください。スタック オーバーフローを修正したら、CUDA コード自体も機能するように再設計する必要があるからです。

于 2011-05-30T04:59:35.653 に答える