2014-12-18 3 views
-3

추력을 사용하여 평균 및 표준을 계산하려면 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

합니다.

사용자가 만든 구조체 정의가 분명히있다 mycomplex를 할 템플릿 유형을 정의하기 때문에
min = std::numeric_limits<T>::max(); 
    max = std::numeric_limits<T>::min(); 

, 당신은 할 수 없습니다 : 과제는 다음과 같은 유형의 감각을하게하는 그것은 POD 데이터 유형에 대해 올바르게 작동하도록 설계되었습니다 스칼라 값에서 구조체로의 직접적인 할당. 아마도 더 정확한 설명은 이 T = mycomplex 일 때 반환 할 엔터티를 알지 못한다는 것입니다.

코드 재사용의 관점에서 자신의 복잡한 구조를 정의하는 대신 CUDA 헤더 cuComplex.h를 선택하여 사용하는 것이 좋습니다. float 기반의 복잡한 데이터와 그 프레임 워크를 사용하여, 당신은 할 수 :

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

기본 코드는 코드를 밀어되기 때문에, 그것은 (그 기능 추력/complex.h에 설명되어 있습니다) 대신 thrust::complex<float>를 사용하는 것이 더 현명한 수 있습니다 . 이것은 잠재적으로 당신이 작성/수정 한 나머지 코드에도 영향을 줄 수 있습니다.

대부분의 나머지 산술은 사용자의 특정 struct 정의에서 작동하도록 변환 했으므로 나머지는 cout에 대한 << 연산자를 처리하는 것입니다. 이는 데이터 유형에 <<을 오버로드하거나 오류가있는 행을 cout이 이해하는 (즉, 실수 부와 허수 부 분을 별도로 출력하는) 데이터 유형으로 구분하여 수행 할 수 있습니다.

+0

: 좋아요, 숫자 제한을 변경했고 FLT_MAX 및 FLT_MIN을 사용했습니다. 마지막 오류 만 받았습니다. 작동하도록하는 방법이 있습니까? 아니면 모든 사용자에 대해 내 연산자를 구현해야 할 것이라고 말한 것입니다. 기능? – George

+0

'FLT_MIN' (가장 작은 양의 정규화 된 float)이 당신이 원하는 것이라고 생각하지 않는다면, 아마도'-FLT_MAX' (가장 작은 float,'std :: numeric_limits :: lowest()'에 해당)를 원할 것입니다. 또한'std :: complex '을 사용하지 않는 이유는 무엇입니까? 그렇지 않다면, 답이 말했듯이, 당신은'operator <<'와 다른 것을 구현해야 할 것입니다. –

+0

'std :: complex '은 아마도'__device__' 함수에서 작동하지 않을 것이지만'thrust :: complex '는 그렇게 될 것입니다. –