как работать над задачей, пока остальные потоки заканчивают работать

0

Предположим, у меня есть цикл OpenMP 2.0 for, который выполняет некоторую операцию:

#pragma omp parallel for schedule(static)
for (int i = 0; i < lim; ++i)
{
  // do something thread-safe
}
threadSafeFunc();

unSafeFunc();

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

Как мне это сделать?

  • 0
    @JerryCoffin Я удивлен, услышав это. Я бы подумал, что это будет относительно распространенный вариант использования.
  • 1
    @JerryCoffin Можете ли вы мотивировать предыдущее утверждение? Последний стандарт, кажется, поддерживает намного больше вещей, чем простые конструкции цикла ...
Показать ещё 1 комментарий
Теги:
multithreading
openmp

1 ответ

3
Лучший ответ

Это может быть решением вашей конкретной проблемы:

#pragma omp parallel 
{ // #1
  #pragma omp for schedule(static) nowait
  for (int i = 0; i < lim; ++i) // #2
  {
    // do something thread-safe
  } // No implied barrier bue to the nowait clause
  #pragma omp single
  { // #3
    threadSafeFunc();
  } // Implied barrier
} // End of parallel region
unSafeFunc();

Идея довольно проста: сначала вы открываете parallel область в #1. Внутри этой параллельной области вы используете две конструкции для работы:

  1. конструкция цикла в #2
  2. единственная конструкция в #3

Конструкция цикла (раздел 2.7.1 стандарта) имеет предложение nowait, которое удаляет неявный барьер в конце цикла. Тогда single конструкция (раздел 2.7.3):

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

Комбинация двух конструкций гарантирует, что первый поток, завершивший свою работу в цикле, войдет в single конструкцию и выполнит threadSafeFunc(). Затем все потоки будут синхронизироваться с подразумеваемым барьером и соединяться с master потоком. На этом этапе будет продолжаться только master поток и выполнить unSafeFunc().

Ещё вопросы

Сообщество Overcoder
Наверх
Меню