Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cuda 还原后的不同结果_Cuda_Reduction - Fatal编程技术网

Cuda 还原后的不同结果

Cuda 还原后的不同结果,cuda,reduction,Cuda,Reduction,我有两个简化算法,都是从,所以他们应该是正确的,但第一个(非常有效)给了我一个错误的结果。第二个结果更好,但我希望有更好的准确性。算法中是否有错误,或者我是否做了一些不好的事情 #include <stdio.h> #include <cuda.h> #include <stdlib.h> #include <math.h> #include "cuda_error.h" //Lock definition #ifndef __LOCK_H__

我有两个简化算法,都是从,所以他们应该是正确的,但第一个(非常有效)给了我一个错误的结果。第二个结果更好,但我希望有更好的准确性。算法中是否有错误,或者我是否做了一些不好的事情

#include <stdio.h>
#include <cuda.h>
#include <stdlib.h>
#include <math.h>
#include "cuda_error.h"

//Lock definition
#ifndef __LOCK_H__
#define __LOCK_H__
struct Lock {
int *mutex;
Lock( void ) {
CudaSafeCall( cudaMalloc( (void**)&mutex,
sizeof(int) ) );
CudaSafeCall( cudaMemset( mutex, 0, sizeof(int) ) );
}
~Lock( void ) {
cudaFree( mutex );
}
__device__ void lock( void ) {
while( atomicCAS( mutex, 0, 1 ) != 0 );
}
__device__ void unlock( void ) {
atomicExch( mutex, 0 );
}
};
#endif
//-------------------------


const int N = 507904;
const int blockSize = 256;
int blocks = N/blockSize;

template <unsigned int blockSize>
__global__ void reduce(Lock lock, float *g_idata, float *g_odata, int n)
{
      extern __shared__ int sdata[];
      unsigned int tid = threadIdx.x;
      unsigned int i = blockIdx.x*(blockSize*2) + tid;
      unsigned int gridSize = blockSize*2*gridDim.x;
      sdata[tid] = 0;

      while (i < n) 
      { 
          sdata[tid] += g_idata[i] + g_idata[i+blockSize]; 
          i += gridSize; 
      }

      __syncthreads();

      if (blockSize >= 512) { if (tid < 256) { sdata[tid] += sdata[tid + 256]; } __syncthreads(); }
      if (blockSize >= 256) { if (tid < 128) { sdata[tid] += sdata[tid + 128]; } __syncthreads(); }
      if (blockSize >= 128) { if (tid < 64) { sdata[tid] += sdata[tid + 64]; } __syncthreads(); }

      if (tid < 32) 
      {
          if (blockSize >= 64) sdata[tid] += sdata[tid + 32];
          if (blockSize >= 32) sdata[tid] += sdata[tid + 16];
          if (blockSize >= 16) sdata[tid] += sdata[tid + 8];
          if (blockSize >= 8) sdata[tid] += sdata[tid + 4];
          if (blockSize >= 4) sdata[tid] += sdata[tid + 2];
          if (blockSize >= 2) sdata[tid] += sdata[tid + 1];
      }

    if (tid == 0)
    {
        lock.lock();        
        *g_odata += sdata[0];
        lock.unlock();
    }

}

__global__ void reduction_sum(Lock lock,float *in, float *out, int N) 
{
    extern __shared__ float sf_data[];
    int tid = threadIdx.x;
    int i = blockIdx.x * blockDim.x + threadIdx.x;

    sf_data[tid] = (i<N) ? in[i] : 0;

    __syncthreads();

    for (int s = blockDim.x/2; s>0; s>>=1) 
    {
      if (tid < s) 
        {
        sf_data[tid] += sf_data[tid + s];
      }
      __syncthreads();
    }

    if (tid == 0)
    {
        lock.lock();        
        *out += sf_data[0];
        lock.unlock();
    }
}
//initializing function
double los()
{
    return (double)rand()/(double)RAND_MAX;
}
//-------------------------------------------


int main (void)
{

//memory allocation 
    float *a;
    float *dev_a, *dev_blocksum1, *dev_blocksum2;
    float s1=0, s2=0, spr=0;

    a = (float*)malloc( N*sizeof(float) );
    CudaSafeCall( cudaMalloc( (void**)&dev_a, N*sizeof(float) ) );
    CudaSafeCall( cudaMemset( dev_a, 0, N*sizeof(float) ) );
    CudaSafeCall( cudaMalloc( (void**)&dev_blocksum1, sizeof(float) ) );
    CudaSafeCall( cudaMalloc(   (void**)&dev_blocksum2, sizeof(float)   )   );
    CudaSafeCall( cudaMemset( dev_blocksum1, 0, sizeof(float) ) );
    CudaSafeCall( cudaMemset( dev_blocksum2, 0, sizeof(float) ) );
//--------------------

//drawing, array fill
    srand(2403);
    int i;
    for (i=0; i<N; i++)
    {
        a[i]=los();
        spr+=a[i];
    }
    printf("CPU sum: %f \n", spr);
//copy HtoD
    CudaSafeCall( cudaMemcpy( dev_a, a, N*sizeof(float), cudaMemcpyHostToDevice ) );
//---------------------

Lock lock;

//reduce
    reduce<blockSize><<<blocks, blockSize, blockSize*sizeof(float)>>>(lock, dev_a, dev_blocksum1, N);
    CudaSafeCall(   cudaMemcpy ( &s1, dev_blocksum1, sizeof(float), cudaMemcpyDeviceToHost  )   );
    printf("GPU sum1: %f \n", s1);
//-----------------------

//reduction_sum
    reduction_sum<<<blocks, blockSize, blockSize*sizeof(float)>>>(lock, dev_a, dev_blocksum2, N);
    CudaSafeCall(   cudaMemcpy ( &s2, dev_blocksum2, sizeof(float), cudaMemcpyDeviceToHost  )   );
    printf("GPU sum2: %f \n", s2);
//---------------------

    return 0;
}

$ CPU sum: 253833.515625 
$ GPU sum1: 14021.000000 
$ GPU sum2: 253835.906250 
#包括
#包括
#包括
#包括
#包括“cuda_error.h”
//锁定定义
#如果没有锁定__
#定义锁__
结构锁{
int*互斥;
锁(空){
CudaSafeCall(cudamaloc((void**)和互斥),
sizeof(int));
CudaSafeCall(cudaMemset(互斥,0,sizeof(int));
}
~Lock(无效){
cudaFree(互斥);
}
__设备无效锁(无效){
while(atomicCAS(互斥,0,1)!=0);
}
__设备\无效解锁(无效){
原子exch(互斥,0);
}
};
#恩迪夫
//-------------------------
常数int N=507904;
const int blockSize=256;
int blocks=N/块大小;
模板
__全局无效减少(锁锁锁、浮点*g_idata、浮点*g_odata、int n)
{
外部共享数据数据[];
unsigned int tid=threadIdx.x;
无符号整数i=blockIdx.x*(blockSize*2)+tid;
unsigned int gridSize=blockSize*2*gridDim.x;
sdata[tid]=0;
而(i=512){if(tid<256){sdata[tid]+=sdata[tid+256];}
if(blockSize>=256){if(tid<128){sdata[tid]+=sdata[tid+128];}
if(blockSize>=128){if(tid<64){sdata[tid]+=sdata[tid+64];}
如果(tid<32)
{
如果(块大小>=64)sdata[tid]+=sdata[tid+32];
如果(块大小>=32)sdata[tid]+=sdata[tid+16];
如果(块大小>=16)sdata[tid]+=sdata[tid+8];
如果(块大小>=8)sdata[tid]+=sdata[tid+4];
如果(块大小>=4)sdata[tid]+=sdata[tid+2];
如果(块大小>=2)sdata[tid]+=sdata[tid+1];
}
如果(tid==0)
{
lock.lock();
*g_odata+=sdata[0];
lock.unlock();
}
}
__全局无效缩减总和(锁定、浮点*输入、浮点*输出、整数N)
{
外部共享浮点sf_数据[];
int tid=threadIdx.x;
int i=blockIdx.x*blockDim.x+threadIdx.x;
sf_数据[tid]=(i0;s>>=1)
{
如果(tid对于(i=0;i而言,有许多事情值得一提

  • 我不确定您的错误检查是否有效。您尚未显示实现此功能的文件,当我使用
    cuda memcheck
    运行您的代码时,报告了各种错误。它们似乎都与锁定功能有关

  • 我不知道你为什么要使用lock函数,我不建议你使用它。根据你使用它的方式,我不认为你认为它超出了范围。我建议使用
    atomicAdd
    ,它应该更快更简单。至少,注释掉
    cudaFree()
    析构函数中的语句

  • 您正在链接到一个旧的演示文稿。如果您查看一个演示文稿,我想您会看到它现在建议使用
    volatile
    。我不会为您重写整个代码,也不会再次总结该白皮书,但如果您只是为了演示目的将
    volatile
    添加到共享内存声明中,它会修复由此产生的问题

  • 您的共享内存变量声明为
    int
    ,但您正在对
    float
    数量求和。这不会按您希望的方式工作。您可以这样声明:

    extern __shared__ volatile float sdata[];
    
  • 以上更改使代码“正常工作”。剩下的是CPU和GPU结果之间的差异。我相信这是由于CPU(串行缩减)和GPU(并行缩减)上的浮点操作顺序不同。由于差异出现在
    浮点数
    数量的第6个有效位,我建议这完全在比较浮点数结果的合理范围内。如果您希望获得更高的准确性,您可以尝试从
    浮点数
    切换到
    双精度
    。此外,还有各种浮点数您可能希望阅读有助于理解的内容,如和


  • 你能添加正确的结果吗?永远不要假设NVidia的代码总是正确的。事实并非如此。这也扩展到了CUDA文档,早期大部分文档都是由实习生编写的,仍然萦绕在他们的网站和互联网上。但除此之外,这可能只是一个数字稳定性的例子。此外,还有一些问题“为什么这不起作用”当然也应该参考输入数据;否则就很难理解出了什么问题。@fxm,我假设CPU总和是正确的结果。谢谢你的回答,在阅读了第4节之后,我感到很惭愧,但我一整天都找不到这个错误。我从“CUDA by EXAME”中获得了锁定方案