Для синхронизации вы можете использовать #pragma omp critical
или использовать процедуры блокировки OpenMP (omp_{init,set,unset,destroy}_lock
).
Преимуществами #pragma omp critical
являются простота и возможность игнорировать прагму, когда известно, что параллельная область выполняется одним потоком.Недостатками являются применимость только к одной параллельной области и глобальный эффект в этой области: ни один другой поток не может выполнить любую другую критическую секцию в области.
Процедуры блокировки OpenMP аналогичны большинству других доступных блокировок, напримерpthreads или Boost (RAII в сторону).Вы инициализируете объект блокировки, затем используете его для защиты определенных критических секций и уничтожаете, когда в этом нет необходимости.Эти блокировки могут использоваться для защиты доступа к данным из разных параллельных областей, для построения схемы распределенной блокировки и т. Д .;но всегда возникают определенные накладные расходы, и, конечно, их использование более «волосатое» по сравнению с #pragma omp critical
.
Однако я бы бросил вызов дизайну параллельного решения.Стирание элемента из середины вектора делает все итераторы недействительными и перемещает элементы.Стирание, предположительно, является редкой операцией (в противном случае выбор вектора был бы сомнительным даже в последовательном коде, я думаю), но из-за вышеупомянутых эффектов вам придется защищать также все чтения вектора, и это, вероятно, будет дорогостоящим.Блокировки чтения / записи могут дать некоторое облегчение, но они недоступны в OpenMP, поэтому вам нужно будет использовать либо интерфейсы, специфичные для платформы, либо стороннюю библиотеку.
Я думаю, что следующее потенциально будет работать лучше:
- Вы сохраняете векторы регулярных выражений закрытыми и добавляете общий вектор флагов одинакового размера, которые указывают, является ли определенное регулярное выражение все еще действительным или нет.
- Перед применением определенного регулярного выражения из частногоvector, код проверяет в общем векторе, не было ли это регулярное выражение "стерто" каким-либо другим потоком.Если это так, регулярное выражение пропускается.
- Найдя совпадение, код помечает элемент общего вектора, который соответствует текущему регулярному выражению, как «стертый», так что теперь он будет игнорироваться.
В этой схеме существуют гонки для флагов чтения / записи: флаг может быть установлен на «стирание» в следующий момент, когда он был прочитан как «действительный» другим потоком.В результате два разных потока могут одновременно найти совпадение для одного и того же регулярного выражения.Однако эта проблема, как я полагаю, существует в вашем текущем решении, где все контейнеры регулярных выражений являются частными, а также в решении с общим контейнером и блокировками или блокировками RW, если только блокировка без RW не защищает также работу с данным регулярным выражением.В случае, если множественные совпадения являются проблемой, все это следует пересмотреть.