2014-12-18 3 views
-3

Я хочу вычислить среднее значение и std с помощью тяги, и я нашел 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): error: no suitable constructor exists to convert from "int" to "mycomplex"

....include/c++/4.4.7/limits(282): error: no suitable constructor exists to convert from "int" to "mycomplex"

...include/c++/4.4.7/bits/stream_iterator.h(191): error: no operator "<<" matches these operands

+0

Downvoting? Почему? – George

ответ

5

код не был изначально разработан для работы со сложным значением (то есть произвольная структура). Он был разработан для правильной работы для типов данных 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> вместо (функции которого изложены в нажимной/complex.h) , Это может потенциально повлиять на остальную часть кода, который вы написали/изменили.

Я вижу, что вы преобразовали большую часть остальной части арифметики, чтобы работать над определением вашей конкретной структуры, поэтому, возможно, единственной оставшейся задачей было бы заняться оператором для cout. Это можно сделать, перегрузив << для вашего типа данных или сломав линию, которая имеет ошибку в типах данных, которую cout понимает (т. Е. Выводит реальную и мнимую части отдельно).

+0

: Хорошо, я изменил числовые ограничения, и я использовал FLT_MAX и FLT_MIN. Теперь я получаю только последнюю ошибку. Есть ли способ заставить ее работать? Или, как вы сказали, мне придется реализовать своих собственных операторов для каждого функционировать? – George

+0

Я не думаю, что 'FLT_MIN' (наименьший положительный нормализованный float) - это то, что вы хотите, вы, вероятно, хотите' -FLT_MAX' (самый маленький float, эквивалентный 'std :: numeric_limits :: lower()'). Также почему бы не использовать 'std :: complex '? В противном случае да, как говорится в ответе, вам придется реализовать 'operator <<' и другие. –

+0

'std :: complex ' вероятно, не будет работать в '__device__', но' thrust :: complex 'будет. –

Смежные вопросы