我想用推力计算均值和标准,我发现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;匹配这些操作数
答案 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
,或将具有错误的行分解为<<
理解的数据类型(即分别输出实部和虚部)来完成。