使用推力进行统计,编译错误

时间:2014-12-18 16:55:55

标签: cuda thrust

我想用推力计算均值和标准,我发现this code。 我试图使用复杂的值,我遇到了一些问题。

以下是代码:

#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/transform_reduce.h>
#include <thrust/functional.h>
#include <thrust/extrema.h>
#include <cmath>
#include <float.h>

typedef struct
{
    float re,im;
} mycomplex;


// structure used to accumulate the moments and other
// statistical properties encountered so far.
template <typename T>
struct summary_stats_data
{
    T n;
    T min;
    T max;
    T mean;
    T M2;

    // initialize to the identity element
    void initialize()
    {
        n.re = mean.re = M2.re = 0;
        n.im = mean.im = M2.im = 0;
        min = std::numeric_limits<T>::max();
        max = std::numeric_limits<T>::min();
    }

    float varianceRe() { return M2.re / ( n.re - 1 ); }
    float varianceIm() { return M2.im / ( n.im - 1 ); }

    float variance_nRe() { return M2.re / n.re; }
    float variance_nIm() { return M2.im / n.im; }

};

// stats_unary_op is a functor that takes in a value x and
// returns a variace_data whose mean value is initialized to x.
template <typename T>
struct summary_stats_unary_op
{
    __host__ __device__
    summary_stats_data<T> operator()(const T& x) const
    {
        summary_stats_data<T> result;
        result.n.re = 1;
        result.n.im = 1;

        result.min = x;
        result.max = x;

        result.mean = x;

        result.M2.re = 0;
        result.M2.im = 0;

        return result;
    }

};

// summary_stats_binary_op is a functor that accepts two summary_stats_data
// structs and returns a new summary_stats_data which are an
// approximation to the summary_stats for
// all values that have been agregated so far
template <typename T>
struct summary_stats_binary_op
: public thrust::binary_function<const summary_stats_data<T>&,
const summary_stats_data<T>&,
summary_stats_data<T> >
{
    __host__ __device__
    summary_stats_data<T> operator()(const summary_stats_data<T>& x, const summary_stats_data <T>& y) const
    {
        summary_stats_data<T> result;

        // precompute some common subexpressions
        T n;
        n.re = x.n.re + y.n.re;
        n.im = x.n.im + y.n.im;

        T delta;
        delta.re = y.mean.re - x.mean.re;
        delta.im = y.mean.im - x.mean.im;

        T delta2;
        delta2.re = delta.re * delta.re;
        delta2.im = delta.im * delta.im;

        //Basic number of samples (n), min, and max
        result.n = n;

        result.min.re = thrust::min( x.min.re, y.min.re );
        result.min.im = thrust::min( x.min.im, y.min.im );

        result.max.re = thrust::max( x.max.re, y.max.re );
        result.max.im = thrust::max( x.max.im, y.max.im );

        result.mean.re = x.mean.re + delta.re * y.n.re / n.re;
        result.mean.im = x.mean.im + delta.im * y.n.im / n.im;


        result.M2.re = x.M2.re + y.M2.re;
        result.M2.im = x.M2.im + y.M2.im;

        result.M2.re += delta2.re * x.n.re * y.n.re / n.re;
        result.M2.im += delta2.im * x.n.im * y.n.im / n.im;

        return result;
    }
};

template <typename Iterator>
void print_range(const std::string& name, Iterator first, Iterator last)
{
    typedef typename std::iterator_traits<Iterator>::value_type T;

    std::cout << name << ": ";
    thrust::copy(first, last, std::ostream_iterator<T>(std::cout, " "));
    std::cout << "\n";
}


int main(void)
{
    typedef mycomplex T;

    const int N = 4;

    // initialize host array
    thrust::host_vector<T> h_x(N);

    h_x[ 0 ].re = h_x[ 0 ].im = 4.0f;
    h_x[ 1 ].re = h_x[ 1 ].im = 7.0f;
    h_x[ 2 ].re = h_x[ 2 ].im = 13.0f;
    h_x[ 3 ].re = h_x[ 3 ].im = 16.0f;


    // Copy host_vector H to device_vector D
    thrust::device_vector<T> d_x = h_x;

    // setup arguments
    summary_stats_unary_op<T> unary_op;
    summary_stats_binary_op<T> binary_op;
    summary_stats_data<T> init;

    init.initialize();

    // compute summary statistics
    summary_stats_data<T> result = thrust::transform_reduce( d_x.begin(), d_x.end(), unary_op, init, binary_op );

    std::cout <<"******Summary Statistics Example*****"<<std::endl;
    print_range("The data", d_x.begin(), d_x.end());

    std::cout <<"Count : "<< result.n.re << std::endl;
    std::cout <<"Minimum : "<< result.min.re <<std::endl;
    std::cout <<"Maximum : "<< result.max.re <<std::endl;
    std::cout <<"Mean : "<< result.mean.re << std::endl;
    std::cout <<"Variance : "<< result.varianceRe() << std::endl;
    std::cout <<"Standard Deviation : "<< std::sqrt(result.variance_nRe()) << std::endl;



return 0;
}

我收到错误:

  

.... include / c ++ / 4.4.7 / limits(284):错误:没有合适的构造函数   存在转换为&#34; int&#34;到&#34; mycomplex&#34;

     

.... include / c ++ / 4.4.7 / limits(282):错误:没有合适的构造函数   存在转换为&#34; int&#34;到&#34; mycomplex&#34;

     

... include / c ++ / 4.4.7 / bits / stream_iterator.h(191):错误:无操作符   &#34;&LT;&LT;&#34;匹配这些操作数

1 个答案:

答案 0 :(得分:6)

该代码最初并非设计用于复杂值(即任意结构)。它被设计为适用于POD数据类型,以下类型的赋值是有意义的:

    min = std::numeric_limits<T>::max();
    max = std::numeric_limits<T>::min();

由于您已将模板类型定义为mycomplex,这显然是您创建的结构定义,因此无法从标量值直接赋值给结构。也许更正确的描述可能是std::numeric_limits<T>::max()T = mycomplex时不知道要返回的实体。

从代码重用的角度来看,我建议不要定义自己的复杂结构,而是建议使用CUDA头文件cuComplex.h并使用它。将该框架与基于float的复杂数据一起使用,您可以:

    min = make_cuFloatComplex(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());

由于底层代码是推力代码,因此使用thrust::complex<float>代替它(其功能在thrust / complex.h中概述)可能更为明智。这可能会影响您编写/修改的其余代码。

我看到你已经将大部分算法转换为特定的结构定义,因此唯一剩下的就是处理<<的{​​{1}}运算符。这可以通过为您的数据类型重载cout,或将具有错误的行分解为<<理解的数据类型(即分别输出实部和虚部)来完成。