【问题标题】:Value of sum from thrust::reduce not correct推力::减少的总和值不正确
【发布时间】:2021-04-30 20:49:16
【问题描述】:

我一直在尝试实现一些需要在thrust::device_ptr上调用reduce的代码,结果在处理大值时与CPU实现不一致。我必须处理大值。那么有没有办法解决:

我的代码:

    #include <cuda_runtime_api.h>
    #include <stdio.h>
    #include <thrust/host_vector.h>
    #include <thrust/device_vector.h>
    #include <iostream>
    #define   NZ  412//
    #define   NX  402//
    using namespace std;
    using real =double;
    
    
    void allocate_array_2d(real**& preal, const int dim1, const int dim2) {
        // Contiguous allocation of 2D arrays
    
        preal = new real * [dim1];
        preal[0] = new real[dim1 * dim2];
        for (int i = 1; i < dim1; i++) preal[i] = preal[i - 1] + dim2;
    
        for (int i = 0; i < dim1; i++) {
            for (int j = 0; j < dim2; j++) {
                preal[i][j] = 0;
            }
        }
    }
    #define cudaCheckError(code)                                             \
      {                                                                      \
        if ((code) != cudaSuccess) {                                         \
          fprintf(stderr, "Cuda failure %s:%d: '%s' \n", __FILE__, __LINE__, \
                  cudaGetErrorString(code));                                 \
        }                                                                    \
      }
    
    
    int main()
    
    {
        real** a;
        std::cout.precision(30);
        allocate_array_2d(a, NZ, NX);//input array
       
        for (int i = 0; i < NZ; i++) {
            for (int j = 0; j < NX; j++) {
                a[i][j] = 2.14748e+09;
              
              
            }
        }
    
            real* da;
            cudaCheckError(cudaMalloc(&da, NZ * NX  * sizeof(real)));
            cudaCheckError(cudaMemcpy(da,a[0], NZ * NX  * sizeof(real),cudaMemcpyHostToDevice));
    
            ///************************
            //CUDA KERNELS ARE HERE
            // REMOVED FOR CLEAR QUESTION
            ///*************************
      
            real sum1=0;
          
            thrust::device_ptr<real> dev_ptr = thrust::device_pointer_cast(da);
            sum1 = thrust::reduce(dev_ptr, dev_ptr+NZ*NX, 0, thrust::plus<real>());
            
            cout<<" \nsum gpu "<< sum1<<"\n";
    
            real sum2=0;
    
            ////////CPU PART DOING SAME THING//////
            for (int i = 0; i < NZ; i++) {
    
                for (int j = 0; j < NX; j++) {
                   sum2 += a[i][j];
                    
                }
            }
    
    
            cout<<"\nsum cpu "<< sum2<<"\n";
            if((sum2-sum1)<0.001)
            std::cout << "\nSUCESS "<< "\n";
            else
            std::cout << "\nFailure & by "<<sum2-sum1<< "\n";
       
    }

我使用的编译器是 nvcc,我的显卡是 nvidia 1650,计算能力 7.5。

【问题讨论】:

    标签: parallel-processing cuda nvidia hpc thrust


    【解决方案1】:

    根据the documentation,thrust 期望求和的类型反映在init 值中:

    sum1 = thrust::reduce(dev_ptr, dev_ptr+NZ*NX, 0, thrust::plus<real>());
                                                  ^
    

    你拥有的那个常量的类型是一个整数类型。如果将其更改为双精度常量:

    sum1 = thrust::reduce(dev_ptr, dev_ptr+NZ*NX, 0.0, thrust::plus<real>());
    

    根据我的测试,您会在 CPU 和 GPU 之间获得匹配的结果。 (您也可以将常量转换为 real 类型:(real)0 并使用它,还有其他方法可以解决这个问题,例如放弃使用 init 值和二进制操作。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-28
      • 1970-01-01
      • 2021-02-11
      • 1970-01-01
      • 1970-01-01
      • 2018-08-05
      • 2020-07-12
      • 2011-01-05
      相关资源
      最近更新 更多