УДК 004.272 ПАРАЛЛЕЛЬНАЯ РЕАЛИЗАЦИЯ АЛГОРИТМОВ

реклама
УДК 004.272
ПАРАЛЛЕЛЬНАЯ РЕАЛИЗАЦИЯ АЛГОРИТМОВ ПОИСКА СТРОК
Магарёв В.В.
Северо-Казахстанский государственный университет им. М.Козыбаева,
Петропавловск
Научный руководитель – Куликов В.П.
Цель данной работы – путем распараллеливания существующих алгоритмов, добиться
увеличения производительности поиска информации.
Были отобраны 10 наиболее распространенных алгоритмов поиска строк, которые
представлены в таблице. Вычисления произведены на видеокарте с использованием
технологии NVIDIA CUDA, предназначенной для разработки приложений для массивнопараллельных вычислительных устройств. На сегодняшний момент поддерживаемыми
устройствами являются все GPU компании NVIDIA, начиная с серии GeForce8, а также
специализированные для решения расчетных задач GPU семейства Tesla.
Основные преимущества CUDA: простота (все программы пишутся на
«расширенном» языке С), наличие хорошей документации, набор готовых инструментов,
включающих
профайлер,
набор
готовых
библиотек,
кроссплатформенность
(поддерживаются Microsoft Windows, Linux и Mac OS X).
CUDA строится на концепции, что GPU (называемый устройством, device) выступает
в роли массивно-параллельного сопроцессора к CPU (называемому host). Программа на
CUDA задействует как CPU, так и GPU. При этом обычный (последовательный, то есть
непараллельный) код выполняется на CPU, а для массивно-параллельных вычислений
соответствующий код выполняется на GPU как набор одновременно выполняющихся
нитей (потоков, threads).
Таким образом, GPU рассматривается как специализированное вычислительное
устройство, которое:
• является сопроцессором к CPU;
• обладает собственной памятью;
• обладает возможностью параллельного выполнения огромного количества
отдельных нитей.
Важным моментом является то, что хотя подобный подход очень похож на работу с
SIMD-моделью, есть и принципиальные отличия (компания NVIDIA использует термин
SIMT – Single Instruction, Multiple Thread). Нити разбиваются на группы по 32 нити,
называемые warps. Только нити в пределах одного warp выполняются физически
одновременно. Нити из разных warp могут находиться на разных стадиях выполнения
программы.
Для решения задач CUDA использует очень большое количество параллельно
выполняемых нитей, при этом обычно каждой нити соответствует один элемент
вычисляемых данных. Все запущенные на выполнение нити организованы в следующую
иерархию (рисунок).
Верхний уровень иерархии – сетка (grid) – соответствует всем нитям, выполняющим
данное ядро. Верхний уровень представляет из себя одномерный или двухмерный массив
блоков (block). Каждый блок – это одномерный, двухмерный или трехмерный массив
нитей (thread). При этом все блоки имеют одинаковую размерность и размер [1].
Поскольку модель вычислений, используемая в CUDA похожа на модель SIMD, т.е.
параллелизм на уровне данных, то напрашивается следующий принцип параллельного
выполнения алгоритмов: исходная строка разбивается на множество мелких подстрок,
затем каждый вычислительный поток ищет образец в своей подстроке, используя
последовательный алгоритм.
Все алгоритмы тестированы на
текстовом файле размером 100 Мбайт, в
конце файла находится искомая строка,
длиной 6 символов.
Если
алгоритм
требует
предварительных вычислений перед
началом поиска, то все предвычисления
выполняются на процессоре, даже в
параллельном
варианте
алгоритма,
поэтому время предвычислений будем
игнорировать,
т.к.
оно
будет
одинаковым в обоих случаях. Также не
будем учитывать время необходимое на
загрузку файла в оперативную память
(оно одинаково). Итак, замеряем время
работы непосредственно алгоритмов
поиска, Рисунок 1. Иерархия нитей в CUDA
без
«накладных
расходов».
Однако следует учесть, что специфика вычислений на видеокарте требует, чтобы
обрабатываемые данные находились во внутренней памяти видеокарты, поэтому для
получения достоверных результатов следует к основному времени выполнения алгоритма
на видеокарте суммировать время загрузки и выгрузки данных.
Для измерения времени работы последовательных версий алгоритмов использовался
профилировщик Intel VTune, а для параллельных алгоритмов – NVIDIA Compute Visual
Profiler.
Чтобы оценить степень влияния оптимизирующего компилятора, все программы
будем компилировать в режимах debug (неоптимизированный) и release
(оптимизированный).
Итоговые результаты приведены в таблице (время измерялось в миллисекундах).
Таблица 1
Алгоритм
Грубой силы
Рабина-Карпа
ДКА
Морриса-Пратта
Кнута-Морриса-Пратта
Бойера-Мура
Бойера-Мура-Хорспула
Быстрый поиск
Райта
Обращения сегмента
Последовательный
Debug
Release
834
461
1078
454
910
599
1343
525
1412
543
443
246
432
285
341
181
369
261
363
192
Параллельный
Debug
Release
295
291
464
478
283
278
318
288
309
291
286
164
138
137
162
167
137
146
140
141
Оптимизация дает значительный прирост производительности для последовательных
алгоритмов, однако для параллельных она практически не имеет смысла.
В среднем, прирост производительности для параллельных алгоритмов составляет 2.9
для неоптимизированного варианта, и 1.6 для оптимизированного. Из этого следует, что
использование параллельных вычислений для поиска строк оправдывает себя.
Литература
1. Боресков А.В., Харламов А.А. Основы работы с технологией CUDA. – М.: ДМК
пресс, 2010, 232 c.
Скачать