На этом шаге мы рассмотрим итераторы.
В библиотеке 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.