Thrust: суммирование элементов массива, индексированного другим массивом [сумма синтаксиса Matlab (x (индексы))]

Я пытаюсь суммировать элементы массива, индексированного другим массивом, с помощью библиотеки Thrust, но не смог найти пример. Другими словами, я хочу реализовать синтаксис Matlab

sum(x(indices))

Вот код руководства, который пытается указать, чего я хочу достичь:

#define N 65536

// device array copied using cudaMemcpyToSymbol
__device__ int global_array[N];

// function to implement with thrust
__device__ int support(unsigned short* _memory, unsigned short* _memShort)
{
   int support = 0;

  for(int i=0; i < _memSizeShort; i++)
        support += global_array[_memory[i]];

  return support;     
}

Кроме того, из основного кода могу ли я использовать global_array[N], не копируя его обратно с помощью cudaMemcpyFromSymbol?

Каждый комментарий/ответ приветствуется :)

Спасибо


person spaghettifunk    schedule 04.05.2012    source источник
comment
Можете ли вы объяснить немного больше о том, что вы пытаетесь сделать? Является ли сумма общей суммой (т. е. предполагается ли, что ваша функция support представляет собой слитный сбор-сокращение) или это что-то еще? Есть ли какая-то причина, по которой вы решили показать support как функцию устройства, или это в принципе не имеет значения?   -  person talonmies    schedule 04.05.2012
comment
Если вы используете Thrust, вы должны кодировать в правильном стиле C++, IMO.   -  person leftaroundabout    schedule 04.05.2012
comment
@talonmies, ты решил мою проблему, просто сказав, что слитный сбор-уменьшение !! Это именно то, что я искал! Но пара вещей: из примера в Кратком руководстве по началу работы (permutation_iterator) они просто перебирают массивы целиком. Вместо этого я хотел бы выполнить итерацию для определенного числа (как в цикле for выше); Как мне это сделать ? И должен ли я скопировать обратно global_array[N] с устройства?   -  person spaghettifunk    schedule 04.05.2012


Ответы (1)


Это очень поздний ответ, предоставленный здесь, чтобы удалить этот вопрос из списка без ответа. Я уверен, что ОП уже нашел решение (с мая 2012 года :-)), но я считаю, что следующее может быть полезно другим пользователям.

Как указал @talonmies, проблема может быть решена с помощью плавного сокращения сбора. Решение действительно представляет собой применение permutation_iterator и reduce Терста. permutation_iterator позволяет (неявно) переупорядочивать целевой массив x в соответствии с индексами в массиве indices. reduce выполняет суммирование (неявно) переупорядоченного массива.

Это приложение является частью документации Thrust, приведенной ниже для удобства.

#include <thrust/iterator/permutation_iterator.h>
#include <thrust/reduce.h>
#include <thrust/device_vector.h>

// this example fuses a gather operation with a reduction for
// greater efficiency than separate gather() and reduce() calls

int main(void)
{
    // gather locations
    thrust::device_vector<int> map(4);
    map[0] = 3;
    map[1] = 1;
    map[2] = 0;
    map[3] = 5;

    // array to gather from
    thrust::device_vector<int> source(6);
    source[0] = 10;
    source[1] = 20;
    source[2] = 30;
    source[3] = 40;
    source[4] = 50;
    source[5] = 60;

    // fuse gather with reduction: 
    //   sum = source[map[0]] + source[map[1]] + ...
    int sum = thrust::reduce(thrust::make_permutation_iterator(source.begin(), map.begin()),
                             thrust::make_permutation_iterator(source.begin(), map.end()));

    // print sum
    std::cout << "sum is " << sum << std::endl;

    return 0;
}

В приведенном выше примере map играет роль indices, а source играет роль x.

Что касается дополнительного вопроса в вашем комментарии (повторение сокращенного количества терминов), достаточно будет изменить следующую строку

int sum = thrust::reduce(thrust::make_permutation_iterator(source.begin(), map.begin()),
                         thrust::make_permutation_iterator(source.begin(), map.end()));

to

int sum = thrust::reduce(thrust::make_permutation_iterator(source.begin(), map.begin()),
                         thrust::make_permutation_iterator(source.begin(), map.begin()+N));

если вы хотите выполнить итерацию только по первым N элементам массива индексации map.

Наконец, что касается возможности использования global_array с хоста, вы должны заметить, что это вектор, находящийся на устройстве, поэтому вам нужен cudaMemcpyFromSymbol, чтобы сначала переместить его на хост.

person Vitality    schedule 26.03.2014