Search code examples
cudathrust

Applying reduction operation using Thrust subject to a boolean condition


I want to use thrust::reduce to find the max value in an array A. However, A[i]should only be chosen as the max if it also satisfies a particular boolean condition in another array B. For example, B[i] should be true. Is their a version of thrust::reduce that does this. I looked at the documentation and found only following API;

thrust::reduce(begin,end, default value, operator)

However, i was curious is their a version more suitable to my problem?

EDIT: Compilation fails in last line!

      typedef thrust::device_ptr<int> IntIterator;
      typedef thrust::device_ptr<float> FloatIterator;
      typedef thrust::tuple<IntIterator,FloatIterator> IteratorTuple;
      typedef thrust::zip_iterator<IteratorTuple> myZipIterator;
      thrust::device_ptr<int> deviceNBMInt(gpuNBMInt);
    thrust::device_ptr<int> deviceIsActive(gpuIsActive);
    thrust::device_ptr<float> deviceNBMSim(gpuNBMSim);

    myZipIterator iter_begin = thrust::make_zip_iterator(thrust::make_tuple(deviceIsActive,deviceNBMSim));
    myZipIterator iter_end = thrust::make_zip_iterator(thrust::make_tuple(deviceIsActive + numRow,deviceNBMSim + numRow));
    myZipIterator result =  thrust::max_element(iter_begin, iter_end, Predicate());

Solution

  • Yes, there is. I guess you should take a look at Extrema And Zip iterator

    Something like this should do the trick (not sure if this code works out of the box):

    typedef thrust::device_ptr<bool>  BoolIterator;
    typedef thrust::device_ptr<float>  ValueIterator;
    
    BoolIterator bools_begin, bools_end;
    ValueIterator values_begin, values_end; 
    // initialize these pointers
    // ...
    
    typedef thrust::tuple<BoolIterator, ValueIterator> IteratorTuple;
    typedef thrust::tuple<bool, value> DereferencedIteratorTuple;
    typedef thrust::zip_iterator<IteratorTuple> ZipIterator;
    
    ZipIterator iter_begin(thrust::make_tuple(bools_begin, values_begin));
    ZipIterator iter_end(thrust::make_tuple(bools_end, values_end));
    
    struct Predicate
    {
      __host__ __device__ bool operator () 
                          (const DereferencedIteratorTuple& lhs, 
                           const DereferencedIteratorTuple& lhs) 
      {
        using thrust::get;
        if (get<0>(lhs) && get<0>(rhs) ) return get<1>(lhs) < get<1>(rhs); else
        return ! get<0>(lhs) ;
      }
    };
    
    ZipIterator result =  thrust::max_element(iter_begin, iter_end, Predicate());
    

    Or you may consider similar technique with zip iterator with thrust::reduce. Or you can try with inner_product Not sure what will work faster.