Общие данные OpenMP - PullRequest
       16

Общие данные OpenMP

3 голосов
/ 10 мая 2011

Я немного новичок в OpenMP, но в целом имею опыт параллельной обработки. Я работал с boost::threads раньше и сейчас тестирую с openmp.

Проблема в том, что я не знаю, как обращаться с общим доступом к данным, потому что я действительно не знаю, что openmp делает внутренне с общими объектами данных внутри параллельных циклов.

Что я делаю сейчас (пока это работает): я читаю файлы с диска в память с помощью mmap. Я получаю указатель на символ после части карты памяти.

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

Я сделал этот список (вектор, содержащий регулярное выражение) закрытым внутри цикла openmp, поэтому каждый поток имеет свою собственную копию этого списка.

Здесь возникает проблема:

Чтобы значительно повысить производительность моего приложения, мне нужно иметь возможность удалять (regex-) элементы из этого вектора, когда они совпадают со строкой.

Теперь всем другим активным потокам нужно как можно скорее удалить этот элемент из списка.

Поэтому я сделал этот список общим объектом данных в цикле openmp, но теперь я получаю ошибки сегментации во время выполнения, когда пытаюсь записать (vector.erase (item #)) в список.

С boost :: threads я бы просто использовал мьютекс для блокировки этого объекта во время записи / чтения.

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

Ответы [ 2 ]

3 голосов
/ 10 мая 2011

Для синхронизации вы можете использовать #pragma omp critical или использовать процедуры блокировки OpenMP (omp_{init,set,unset,destroy}_lock).

Преимуществами #pragma omp critical являются простота и возможность игнорировать прагму, когда известно, что параллельная область выполняется одним потоком.Недостатками являются применимость только к одной параллельной области и глобальный эффект в этой области: ни один другой поток не может выполнить любую другую критическую секцию в области.

Процедуры блокировки OpenMP аналогичны большинству других доступных блокировок, напримерpthreads или Boost (RAII в сторону).Вы инициализируете объект блокировки, затем используете его для защиты определенных критических секций и уничтожаете, когда в этом нет необходимости.Эти блокировки могут использоваться для защиты доступа к данным из разных параллельных областей, для построения схемы распределенной блокировки и т. Д .;но всегда возникают определенные накладные расходы, и, конечно, их использование более «волосатое» по сравнению с #pragma omp critical.

Однако я бы бросил вызов дизайну параллельного решения.Стирание элемента из середины вектора делает все итераторы недействительными и перемещает элементы.Стирание, предположительно, является редкой операцией (в противном случае выбор вектора был бы сомнительным даже в последовательном коде, я думаю), но из-за вышеупомянутых эффектов вам придется защищать также все чтения вектора, и это, вероятно, будет дорогостоящим.Блокировки чтения / записи могут дать некоторое облегчение, но они недоступны в OpenMP, поэтому вам нужно будет использовать либо интерфейсы, специфичные для платформы, либо стороннюю библиотеку.

Я думаю, что следующее потенциально будет работать лучше:

  • Вы сохраняете векторы регулярных выражений закрытыми и добавляете общий вектор флагов одинакового размера, которые указывают, является ли определенное регулярное выражение все еще действительным или нет.
  • Перед применением определенного регулярного выражения из частногоvector, код проверяет в общем векторе, не было ли это регулярное выражение "стерто" каким-либо другим потоком.Если это так, регулярное выражение пропускается.
  • Найдя совпадение, код помечает элемент общего вектора, который соответствует текущему регулярному выражению, как «стертый», так что теперь он будет игнорироваться.

В этой схеме существуют гонки для флагов чтения / записи: флаг может быть установлен на «стирание» в следующий момент, когда он был прочитан как «действительный» другим потоком.В результате два разных потока могут одновременно найти совпадение для одного и того же регулярного выражения.Однако эта проблема, как я полагаю, существует в вашем текущем решении, где все контейнеры регулярных выражений являются частными, а также в решении с общим контейнером и блокировками или блокировками RW, если только блокировка без RW не защищает также работу с данным регулярным выражением.В случае, если множественные совпадения являются проблемой, все это следует пересмотреть.

1 голос
/ 10 мая 2011

Этого можно добиться, создав критическую секцию.

#pragma omp critical
{
   ...some synchronized code...
}

РЕДАКТИРОВАТЬ: Удалена часть о '#pragma omp atomic', поскольку он не может атомарно выполнять необходимые операции.

...