使用多个块时CUDA输出错误

使用多个块时CUDA输出错误,cuda,gpu,fft,Cuda,Gpu,Fft,我正在尝试使用VisualStudio2010在CUDA中开发FFT的实现,到目前为止,我已经使它在一个块内的1024个点上工作。问题是,每当我使用多个块时,块1的结果将是正常的,而其他块将返回一个错误的值(看起来不是随机的,它们不会在多次运行中改变) __device__ void FFT(int idxS,int bfsize, Complex* data1, Complex* data0, int k, int N ){ Complex alpha; if(

我正在尝试使用VisualStudio2010在CUDA中开发FFT的实现,到目前为止,我已经使它在一个块内的1024个点上工作。问题是,每当我使用多个块时,块1的结果将是正常的,而其他块将返回一个错误的值(看起来不是随机的,它们不会在多次运行中改变)

__device__ void FFT(int idxS,int bfsize, Complex* data1, Complex* data0, int k, int N ){
        Complex alpha;
        if((idxS % bfsize) < (bfsize/2)){
            data1[idxS] = ComplexAdd(data0[idxS],data0[idxS+bfsize/2]);
        }
        else
        {
            float angle = -PI*2*((idxS*(1<<k)%(bfsize/2)))/N;
            alpha.x = cos(angle);
            alpha.y= sin(angle);
            Complex v0;
            v0 = ComplexAdd(data0[idxS-bfsize/2] ,ComplexScale(data0[idxS],-1));
            data1[idxS] = ComplexMul(v0, alpha);
        }
       }

__device__ void Ordenador(int r, int idxS ,Complex* data1, Complex* data0 ){
    int p = 0;
    for(int k = 0;k < r;k++)
       {
          if(idxS & (1<<k))
          p+=1<<(r - k - 1);
        }
    data1[idxS] = data0[p];
    __syncthreads();
}


__global__ void GPU_FFT(int N, int r, Complex* data0, Complex* data1, int k) {
    int idxS = threadIdx.x+ blockIdx.x * blockDim.x;
        __syncthreads;
        int bfsize = 1<<(r - k);
        FFT(idxS, bfsize,  data1,  data0, k, N);
        data0[idxS] = data1[idxS];
   }
int prepFFT(float *Entrada, Complex* saida, int N ){
    if(ceilf(log2((float)N)) == log2((float)N) ){
        for (int i=0; i<N; i++){
            saida[i].x = Entrada[i];
            saida[i].y = 0;
        }
        Complex *d_saida;
        int m = (int)log2((float)N);
        Complex *data1 = new Complex[N];
        Complex *data1_d;
        if (N<1024){
        HANDLE_ERROR (cudaMalloc((void**)&d_saida,   sizeof(Complex) * N));
        HANDLE_ERROR (cudaMemcpy(d_saida,saida, sizeof(Complex)*N, cudaMemcpyHostToDevice));
        HANDLE_ERROR (cudaMalloc((void**)&data1_d,   sizeof(Complex) * N));
        HANDLE_ERROR (cudaMemcpy(data1_d,data1, sizeof(Complex)*N, cudaMemcpyHostToDevice));
        const dim3 numThreads (N,1,1);
        const dim3 numBlocks(1,1,1);
            for(int k = 0 ;k < m ; k++)
    {
        GPU_FFT<<<numBlocks,numThreads, N*2>>>( N, m, d_saida, data1_d, k);
        HANDLE_ERROR (cudaDeviceSynchronize()); 
    }
        HANDLE_ERROR (cudaDeviceSynchronize()); 
        HANDLE_ERROR (cudaMemcpy(saida,data1_d, sizeof(Complex)*N, cudaMemcpyDeviceToHost));
        HANDLE_ERROR (cudaDeviceSynchronize());
        }
        else{
        HANDLE_ERROR (cudaMalloc((void**)&d_saida,   sizeof(Complex) * N));
        HANDLE_ERROR (cudaMemcpy(d_saida,saida, sizeof(Complex)*N, cudaMemcpyHostToDevice));
        HANDLE_ERROR (cudaMalloc((void**)&data1_d,   sizeof(Complex) * N));
        HANDLE_ERROR (cudaMemcpy(data1_d,data1, sizeof(Complex)*N, cudaMemcpyHostToDevice));
        const dim3 numThreads (1024,1,1);
        const dim3 numBlocks(N/1024 +1,1,1);
            for(int k = 0;k < m;k++)
    {
        GPU_FFT<<<numBlocks,numThreads, N*2>>>( N, m, d_saida, data1_d, k);
        HANDLE_ERROR (cudaDeviceSynchronize()); 
    }
        HANDLE_ERROR (cudaMemcpy(saida,data1_d, sizeof(Complex)*N, cudaMemcpyDeviceToHost));
        HANDLE_ERROR (cudaDeviceSynchronize());     
        cudaFree(data1_d);
        cudaFree(d_saida);
        delete data1;

        }
        return 1;
    }
    else
        return 0;
}
我发现在一个新函数中分离最后一行并用CPU调用它可以为我产生正确的结果。 谢谢你的帮助!!
致以最良好的祝愿

首先,您应该检查您的主内核函数
\uuuuu global\uuuuuu void GPU\u FFT

只需将其更改为:

__global__ void GPU_FFT(int N, int r, Complex* data0, Complex* data1, int k) {
    int idxS = threadIdx.x+ blockIdx.x * blockDim.x;
        int bfsize = 1<<(r - k);
        //FFT(idxS, bfsize,  data1,  data0, k, N);
        //data0[idxS] = data1[idxS];
        if (idxS  <= N) data0[idxS] = idxS;
   }

我想你这样做是为了学习,但如果不是这样,那么应该指出有一个CUDA库()可以为你做FFT。是的,我这样做是为了学习,稍后我将使用cufft进行比较。感谢您的提醒。在失败的情况下,您可以尝试使用
cuda memcheck
运行代码,看看它是否报告任何访问错误。也许您应该以块2中的线程317为例完成索引,看看您是否可以在全局内存中的数组中发现任何索引问题。“当我使用memcheck时,它会返回正确的结果,但是如果我在没有memcheck的情况下运行,我会得到奇怪的结果" . 这听起来像是比赛条件。使用memcheck运行可能会影响块的执行顺序。代码中可能存在块顺序依赖项。尝试使用racecheck工具运行memcheck。运行
cuda memcheck--help
了解.data0是如何复杂的,所以我改为:全局无效GPU FFT(int N,int r,complex*data0,complex*data1,int k){int idxS=threadIdx.x+blockIdx.x*blockDim.x;如果(idxS第一部分没问题,我无法理解您最后的更改为[idxS]返回errorok,这样做了,我仍然得到了旧的错误。真正奇怪的是,如果我使用memcheck运行它,我得到了正确的结果(尝试了所有选项,没有错误)ok,我们肯定解决了问题。尝试简化设备FFT函数。但是首先,您可以尝试在if((idxS%bfsize)<(bfsize/2))之后放置u syncthreads{我已经更新了答案来澄清它好了,以下是我目前得到的:没有任何同步线程,我得到了很多错误的输出,其中一个在if中稍微少一点,一个在完成if-else语句之后,我从程序中得到了最多的输出,这是输出的一半是正确的。我将尝试简化函数,我说我正在考虑将bfsize计算发送到CPU,将其作为参数传递,并将if-else语句也发送到CPU,以便一次调用一半的代码。
FFT(idxS, bfsize,  data1,  data0, k, N);
data0[idxS] = data1[idxS];
__global__ void GPU_FFT(int N, int r, Complex* data0, Complex* data1, int k) {
    int idxS = threadIdx.x+ blockIdx.x * blockDim.x;
        int bfsize = 1<<(r - k);
        //FFT(idxS, bfsize,  data1,  data0, k, N);
        //data0[idxS] = data1[idxS];
        if (idxS  <= N) data0[idxS] = idxS;
   }
if((idxS % bfsize) < (bfsize/2)){
__syncthreads;
...}