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

Опитвам се да сумирам елементите на масив, индексиран от друг масив, използвайки библиотеката 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 ти реши проблема ми, просто казвайки fused gather-reduction !! Това е точно това, което търсих! Но няколко неща: от примера в Ръководство за бърз старт на Thrust (permutation_iterator), те просто итерират целите масиви. Вместо това, бих искал да повторя за определено число (както цикълът for по-горе); как мога да направя това ? И трябва ли да копирам обратно global_array[N] от устройството?   -  person spaghettifunk    schedule 04.05.2012


Отговори (1)


Това е много късен отговор, предоставен тук, за да премахнете този въпрос от списъка без отговор. Сигурен съм, че OP вече е намерил решение (от май 2012 г. :-)), но вярвам, че следното може да бъде полезно за други потребители.

Както беше посочено от @talonmies, проблемът може да бъде решен чрез слято събиране-намаляване. Решението наистина е приложение на permutation_iterator и reduce на Thurst. 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