Шаг 24.
Технология CUDA.
Библиотека Thrust. Итераторы

    На этом шаге мы рассмотрим итераторы.

    В библиотеке Thrust есть итераторы для разных целей. Их использование со стандартными алгоритмами позволяет охватить многие классы задач.

    В библиотеке Thrust можно выделить 5 видов итераторов:

    Приведем ниже несколько примеров использования итераторов.


    Пример 1. Проиллюстрируем использование constant_iterator.

#include <thrust/iterator/constant_iterator.h>
#include <thrust/reduce.h>
#include <cstdio>
using namespace thrust;

int main(){
 //Создаем итератор и заполняем содержимое значением 10 	
 constant_iterator<int> first(10);
 //Создаем промежуток из 3 элементов
 constant_iterator<int> last = first + 3;

 //Находим сумму элементов из созданного промежутка
 int ans = reduce(first, last);

 //Выводим результат на экран
 printf("%d\n", ans);
 return 0;
}

/*
Результат выполнения программы:
30
*/

    Полный текст приложения можно взять здесь.


    Пример 2. Пример с использованием counting_iterator.

#include <thrust/iterator/counting_iterator.h>
#include <thrust/reduce.h>
#include <cstdio>
using namespace thrust;

int main(){
 //Создаем итератор со значением 10
 counting_iterator<int> first(10);
 //Создаем промежуток из элементов 10, 11, 12
 counting_iterator<int> last = first + 3;

 //Находим сумму элементов из созданного промежутка
 int ans = reduce(first, last);

 //Выводим результат на экран
 printf("%d\n", ans);
 return 0;
}

/*
Результат выполнения программы:
33
*/

    Полный текст приложения можно взять здесь.


    Пример 3. Программа с использованием transform_iterator. В данном примере создается вектор и два итератора. Один будет указывать на начало вектора, другой на конец вектора. В качестве операции взята операция смена знака.

#include <thrust/iterator/transform_iterator.h>
#include <thrust/reduce.h>
#include <thrust/device_vector.h>
#include <cstdio>
using namespace thrust;

int main(){
 //Создаем вектор из трех элементов
 device_vector<int> vec(3);

 vec[0] = 10;
 vec[1] = 20;
 vec[2] = 30;

 //Изменяем знак элементов вектора и 
 //находим сумму элементов полученного вектора
 int ans = reduce(make_transform_iterator(vec.begin(), negate<int>()),
                  make_transform_iterator(vec.end(), negate<int>()));

 //Выводим результат на экран
 printf("%d\n", ans);
 return 0;
}

/*
Результат выполнения программы:
-60
*/

    Полный текст приложения можно взять здесь.


    Пример 4. Проиллюстрируем использование permutation_iterator.

#include <thrust/iterator/permutation_iterator.h>
#include <thrust/device_vector.h>
#include <thrust/reduce.h>
#include <cstdio>
using namespace thrust;

int main(){
 //Создадим два вектора
 device_vector<int> map(4);
 device_vector<int> source(6);

 map[0] = 3;
 map[1] = 1;
 map[2] = 0;
 map[3] = 5;

 source[0] = 10;
 source[1] = 20;
 source[2] = 30;
 source[3] = 40;
 source[4] = 50;
 source[5] = 60;

 //Найдем сумму по принципу: 
 //source[map[0]] + source[map[1]] + source[map[2]] + source[map[3]]
 int sum = reduce(make_permutation_iterator(source.begin(), map.begin()),
                  make_permutation_iterator(source.end(), map.end()));

 //Выведем результат на экран
 printf("%d\n", sum); 
 return 0;
}

/*
Результат выполнения программы:
130
*/

    Полный текст приложения можно взять здесь.


    Пример 5. Программа с использованием zip_iterator. В данном примере создаются два итератора пар <int, char>. Потом среди этих пар ищется максимальная пара, т.е. пара, у которой первое значение максимальное. Если таких пар несколько, то найдется пара, у которой второе значение максимальное.

#include <thrust/iterator/zip_iterator.h>
#include <thrust/iterator/constant_iterator.h>
#include <thrust/device_vector.h>
#include <thrust/reduce.h>
#include <cstdio>
using namespace thrust;

//Определим для удобства три новых типа
typedef device_vector<int>::iterator IntIterator;
typedef device_vector<char>::iterator CharIterator;
typedef tuple<IntIterator, CharIterator> TupleIterator;

int main(){
 //Создадим два вектора	
 device_vector<int> A(3);
 device_vector<char> B(3);

 A[0] = 10;
 A[1] = 20;
 A[2] = 30;

 B[0] = 'x';
 B[1] = 'y';
 B[2] = 'z';

 //Создадим два итератора
 zip_iterator<TupleIterator> first = make_zip_iterator(
                                                  make_tuple(A.begin(), B.begin()));
 zip_iterator<TupleIterator> last = make_zip_iterator(make_tuple(A.end(), B.end()));

 //Определим операцию для редуцирования
 maximum<tuple<int, char> > binary_op;
 //Первоначальное значение максимума
 tuple<int, char> init = first[0];

 //Найдем максимальное значение
 tuple<int, char> ans = reduce(first, last, init, binary_op);

 //Выведем результат на экран
 printf("%d %c\n", ans.get<0>(), ans.get<1>());
 return 0;
}

/*
Результат выполнения программы:
30 z
*/

    Полный текст приложения можно взять здесь.

    На следующем шаге мы начнем расматривать примеры использованния технологии CUDA.




Предыдущий шаг Содержание Следующий шаг