Вычисление глобального индекса нити в CUDA

Доброго времени суток! Я уже несколько раз затрагивал тему параллельных вычислений, но все время это были вычисления на старом добром центральном процессоре. А сейчас я вкратце расскажу о технологии CUDA от фирмы NVIDIA, которая расшифровывается как Compute Unified Device Architecture, и служит для того, чтобы выполнять параллельные вычисления на процессоре графического устройства, а именно — видеокарточки NVIDIA.

Grid, Block и Thread в CUDA

Для того, чтобы эффективно программировать с помощью технологии CUDA, в первую очередь нужно освоиться и научиться свободно оперировать основными понятиями вычислительной модели. Их три: грид(grid), блок(block) и нить(thread), последний еще называют потоком, это синонимы.

Grid является самым верхним уровнем абстракции в модели, он трехмерный и состоит из блоков. Например, в гриде размером 2x2x2 содержится 8 блоков. В свою очередь, каждый блок содержит в себе трехмерный массив нитей(threads), которые и являются непосредственными исполнителями вычислений. К примеру, если каждый из 8 блоков содержит 2x2x1 нитей, то всего на устройстве будет 32 рабочих потока, готовых приступить к любым вычислениям, причем работать они будут параллельно.

читать далее «Вычисление глобального индекса нити в CUDA»

Основные директивы OpenMP с примерами

Доброго времени суток, друзья! Как вы могли заметить, я иногда балуюсь с параллельным программированием посредством OpenMP. На данный момент готова заметка о том, как установить и настроить omp в Clion. А из реализаций есть параллельное умножение матриц. Я посчитал, что самое время собрать небольшую шпаргалку по наиболее часто используемым директивам и их параметрам, чтобы можно было сюда заглянуть и освежить их в памяти. Постараюсь на каждую директиву добавить по небольшому, чисто символическому синтаксическому примеру.

Не секрет, что OpenMP доступен на языках C/C++ и Fortran(даже слышал, что и на Java есть), но я буду писать примеры только для C/C++, уж не сердитесь, теория для них все равно одинаковая. Предлагаю ни секунды не терять и приступать к делу.

Общий синтаксис вызова директив OpenMP

Любые дополнительные директивы вызываются с помощью стандартной директивы #pragma, и OpenMP не исключение. Следовательно, для того, чтобы обратиться к директиве нужно написать #pragma omp, и назвать искомую директиву. Справедлива следующая конструкция вызова.

#pragma omp директива [опция1, опция2, ...]

Где «директива» — имя директивы, а опции являются необязательным для вызова, их у разных директив может быть разное количество, о них я тоже вкратце расскажу.

читать далее «Основные директивы OpenMP с примерами»

Рекурсивное вычисление определителя квадратной матрицы на C/C++

Доброго времени суток, дорогие друзья! Я практически не затрагивал алгоритмы с матрицами в своем блоге, разве что показал параллельную реализацию умножения матриц с помощью OpenMP. И сейчас я буду это исправлять, и начну, пожалуй, с вычисления определителя квадратной матрицы. Программное нахождение определителя матрицы это не самая простая задача, именно поэтому для начала я реализую его рекурсивной функцией и только для квадратной матрицы. В тот момент, когда доберусь до матрицы любого размера, обязательно оставлю здесь ссылку.

Формулы вычисления определителя

Формулу через перестановки даже нет смысла рассматривать, потому что она включает в себя n! слагаемых. Вместо этого кратко глянем на значения определителя для матриц разного размера.

Для матриц размера 1х1

Значением определителя является единственный элемент матрицы.

Для матриц размера 2х2

Легко посчитать по формуле через перестановки. det = M[0][0]*M[1][1] — M[0][1]*M[1][0], где M — матрица. В реализации алгоритма эта формула будет использована в условии выхода из рекурсии.

читать далее «Рекурсивное вычисление определителя квадратной матрицы на C/C++»

Пузырьковая сортировка — реализация на C/C++

Раз пошло такое дело и я опубликовал свою реализацию быстрой сортировки, с которой вы можете ознакомиться, то как можно обойти стороной самую популярную сортировку? Вообще, спроси у любого студента: «Какую сортировку ты знаешь?», и получишь ответ: «Пузырьком!». Нельзя просто взять и пройти мимо этого факта, мой святой долг стать одним из тысячи человек, которые опубликуют реализацию сортировки пузырьком. Поэтому усаживайтесь поудобнее, мы начинаем!

Суть пузырьковой сортировки

Алгоритм представляет собой проходы по сортируемому массиву, в которых сравниваются два соседних элемента, и, если порядок в них нарушен, то они меняются местами. За каждый проход минимум один элемент встает на свое место — «всплывает» в массиве.

Проход осуществляется двумя циклами: по i и по j. Внешний цикл по i идет от 0 до size-1, где size — размер массива. Важно заметить, что внутренний цикл достаточно прогнать от 0 до size-i-1 так как на i-ом шаге элементы после i-го индекса уже гарантированно отсортированы.

читать далее «Пузырьковая сортировка — реализация на C/C++»

Реализация простого и быстрого возведения в степень на C/C++

Привет всем. Продолжаю потихоньку публиковать свои реализации известных всем и очень популярных алгоритмов, например, уже успел реализовать супер сложную быструю сортировку. На этот раз отклонюсь чуть ближе к математике и рассмотрю алгоритм быстрого возведения в степень, который часто(или даже скорее всегда) используется в стандартных библиотечных функциях возведениях.

Но прежде, чем начать, почему бы не реализовать обычное возведение? Правильно, нет причин себе в этом отказывать, поехали!

Функция возведения числа в степень

Методом «в лоб», пробежимся в цикле и перемножим число само на себя сколько нужно раз. Работает за O(deg) где deg степень.

читать далее «Реализация простого и быстрого возведения в степень на C/C++»