Применение операции сокращения с использованием Thrust с учетом логического условия

Я хочу использовать thrust::reduce для поиска максимального значения в массиве A. Однако A[i] следует выбирать в качестве максимального только в том случае, если оно также удовлетворяет определенному логическому условию в другом массиве B. Например, B[i] должно быть истинным. Это их версия тяги:: уменьшить, которая делает это. Я просмотрел документацию и нашел только следующий API;

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

Однако мне было любопытно, подходит ли их версия для моей проблемы?

РЕДАКТИРОВАТЬ: Компиляция завершается ошибкой в ​​последней строке!

      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());

person Programmer    schedule 21.12.2012    source источник


Ответы (1)


Да, есть. Думаю, вам стоит взглянуть на Extrema и Итератор ZIP

Что-то вроде этого должно помочь (не уверен, что этот код работает из коробки):

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());

Или вы можете рассмотреть аналогичную технику с zip-итератором с thrust::reduce. Или вы можете попробовать с inner_product. Не знаю, что будет работать быстрее.

person Oleg Titov    schedule 21.12.2012
comment
Что означает get‹0›(lhs). Кроме того, если условие if оценивается как ложное, что происходит? - person Programmer; 21.12.2012
comment
@Programmer Извините, должно быть thrust::get<0>(lhs). Описано здесь thrust.github.com/doc/ - person Oleg Titov; 21.12.2012
comment
Что произойдет, если условие if окажется ложным? - person Programmer; 21.12.2012
comment
Я думаю, что я переоптимизировал код. Это предикат "меньше чем". if условие оценивает false означает, что один или логический флаг ложны, поэтому нам нужно исключить соответствующее значение. Поэтому мы проверяем, следует ли исключить аргумент lhs (thrust::get<0>(lhs) == false), и если это правда, предикат возвращает true, что означает «lhs меньше, чем rhs». Если (thrust::get<0>(lhs) == true) , то компонент правой стороны должен быть исключен, а предикат возвращает false, что означает «lhs не меньше, чем rhs» - person Oleg Titov; 21.12.2012
comment
Я оборачивал необработанный ptr в ptr устройства, чтобы использовать thrust::max_element. Мне было любопытно, работает ли 'thrust::device_vector‹type›::iterator' для device_ptr. То есть, можем ли мы определить итераторы для указателей устройств - person Programmer; 21.12.2012
comment
Поскольку все алгоритмы тяги являются шаблонами, вы можете использовать device_ptr вместо итераторов. Помните, что итератор по определению является обобщением указателя. :) - person Oleg Titov; 21.12.2012
comment
Но как бы изменился предложенный вами код, если бы мы использовали device_ptr :) - person Programmer; 21.12.2012
comment
Замените все thrust::device_vector<blah_blah>::iterator на device_ptr<blah_blah> и исправьте iter_begin и iter_end. И я нашел ошибку в примере кода. Вы должны разыменовать результаты get<>(), так как он вернет итератор или указатель. (я исправил) - person Oleg Titov; 21.12.2012
comment
Хорошо! Но можете ли вы сформировать тягу:: кортеж, используя 2 device_ptr? Если нет, вы также не можете сформировать итератор zip. Я буду очень признателен, если вы сможете изменить код, чтобы показать мне изменения, так как у меня немного мало времени. - person Programmer; 21.12.2012
comment
Хотя я принял ваш ответ, моя версия вашего кода не компилируется. Я изменил исходный вопрос, чтобы показать вам мой код. Я буду очень признателен, если вы сможете быстро взглянуть и сообщить мне, если я делаю какие-либо глупые ошибки. - person Programmer; 22.12.2012
comment
Я исправил код в своем посте. Это не было глупой ошибкой. Это была моя ошибка. В моем предикате использовались неправильные типы аргументов. Он должен принимать тип итератора с отложенным именем, но итератор zip слишком умен. «Разыменование возвращает кортеж, созданный из разыменованных итераторов в кортеже итератора». (Из Thrust/zip_iterator.h, строка 186) Не ожидал такого. - person Oleg Titov; 22.12.2012