2012-05-10 2 views
1

추력을 사용하여 값 배열의 최소 및 최대 값을 줄이려고 시도했지만 멈추었습니다. 주어진 float 배열을 사용하여 하나의 패스에서 최소값과 최대 값을 줄이는 대신 thrust의 reduce 메서드를 사용하여 대신 모든 템플릿 컴파일 오류의 어머니 (또는 최소한 아줌마)를 얻습니다.추력 감소가 같지 않은 입/출력 유형으로 작동하지 않습니다.

내 원본 코드에는 2 개의 float4 배열에 분산 된 5 개의 값 목록이 포함되어 있습니다. 그러나이 간단한 예제로 압축했습니다.

struct ReduceMinMax { 
    __host__ __device__ 
    float2 operator()(float lhs, float rhs) { 
     return make_float2(Min(lhs, rhs), Max(lhs, rhs)); 
    } 
}; 

int main(int argc, char *argv[]){ 

    thrust::device_vector<float> hat(4); 
    hat[0] = 3; 
    hat[1] = 5; 
    hat[2] = 6; 
    hat[3] = 1; 

    ReduceMinMax binary_op_of_dooooom; 
    thrust::reduce(hat.begin(), hat.end(), 4.0f, binary_op_of_dooooom); 
} 

대신 2 축소로 나누면 물론 작동합니다. 내 질문은 다음과 같습니다. 추력과 방법으로 한 번에 최소와 최대를 모두 줄일 수 있습니까? 그렇지 않다면 그 감소를 달성하는 가장 효율적인 방법은 무엇입니까? 변환 반복자 나 도움이 될 것입니다 (그래서 경우를, 감소는 원 패스 감소 될 것인가?)

몇 가지 추가 정보 : (CUDA 4.2.7가 제공하는) 내가 1.5 추력 사용하고 내 실제 코드 줄일뿐 아니라 reduce_by_key를 사용하고 있습니다. 이 질문을 쓰는 동안 transform_reduce가 발견되었지만 키를 고려하지 않았습니다.

+3

이진 연산자 함수는 인수 유형에서 다른 반환 유형을 가질 수 없습니다. 어쨌든'thrust :: reduce'를 왜 사용하고 있습니까? 'thrust :: minmax_element'을 사용할 수 없습니까? – talonmies

+3

@gpu : ArrayFire 용 플러그를 할 때마다 AccelerEyes에서 일한다는 것을 공개해야합니다. –

+2

@gpu : 질문을하는 사람이 여러 GPU에 배포해야하거나 무료 버전의 요구 사항을 벗어나는 다른 기능을 필요로하는지 알 수 없으므로 ArrayFire를 무료로 사용할 수 있다고 말하는 것은 오해의 소지가 있습니다. . 가격은 2 GPU 당 연간 2,500 달러입니다. –

답변

3

talonmies 노트로 thrust::reduce는 이항 연산자의 인수 유형은 결과 유형과 일치 할 것으로 예상하기 때문에, 당신의 감소는 컴파일되지 않습니다, 그러나 그것의 결과 유형이 float2 동안 ReduceMinMax의 인수 유형은 float입니다.

thrust::minmax_element

직접이 작업을 구현하지만 대신 thrust::reduce을 일반화 thrust::inner_product와 감소를 구현할 수 필요한 경우 :

#include <thrust/inner_product.h> 
#include <thrust/device_vector.h> 
#include <thrust/extrema.h> 
#include <cassert> 

struct minmax_float 
{ 
    __host__ __device__ 
    float2 operator()(float lhs, float rhs) 
    { 
    return make_float2(thrust::min(lhs, rhs), thrust::max(lhs, rhs)); 
    } 
}; 

struct minmax_float2 
{ 
    __host__ __device__ 
    float2 operator()(float2 lhs, float2 rhs) 
    { 
    return make_float2(thrust::min(lhs.x, rhs.x), thrust::max(lhs.y, rhs.y)); 
    } 
}; 

float2 minmax1(const thrust::device_vector<float> &x) 
{ 
    return thrust::inner_product(x.begin(), x.end(), x.begin(), make_float2(4.0, 4.0f), minmax_float2(), minmax_float()); 
} 

float2 minmax2(const thrust::device_vector<float> &x) 
{ 
    using namespace thrust; 
    pair<device_vector<float>::const_iterator, device_vector<float>::const_iterator> ptr_to_result; 

    ptr_to_result = minmax_element(x.begin(), x.end()); 

    return make_float2(*ptr_to_result.first, *ptr_to_result.second); 
} 

int main() 
{ 
    thrust::device_vector<float> hat(4); 
    hat[0] = 3; 
    hat[1] = 5; 
    hat[2] = 6; 
    hat[3] = 1; 

    float2 result1 = minmax1(hat); 
    float2 result2 = minmax2(hat); 

    assert(result1.x == result2.x); 
    assert(result1.y == result2.y); 
} 
관련 문제