Инициализация и деинициализация потока OpenMP перед выполнением работы

#c #multithreading #openmp

#c #многопоточность #openmp

Вопрос:

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

Теперь у меня есть очень тривиальная проблема, которую я могу решить параллельно, с которой я хочу попробовать OpenMP . Рассмотрим проблему, которая выглядит следующим образом:

 #pragma omp parallel for num_threads(NUM_THREADS), default(none)
for (auto i = 0; i < count; i  )
{
    api_process(i);
}
  

Это не сработает, потому что рабочие потоки OpenMP не вызывали api_start() или api_stop() поэтому рабочим решением было бы:

 #pragma omp parallel for num_threads(NUM_THREADS), default(none)
for (auto i = 0; i < count; i  )
{
    api_start();
    api_process(i);
    api_stop();
}
  

Но это решение приведет к накладным расходам, потому что теперь поток вызывает api_start() и api_stop() несколько раз (если NUM_THREADS < count ).

Итак, мой вопрос: есть ли способ в OpenMP определить функцию для вызова для каждого созданного потока один раз при запуске и один раз при удалении?

Заранее спасибо!

Ответ №1:

Вы можете вызывать функции вручную в начале / конце первой / последней итерации соответственно или использовать что-то как std::call_once . Однако это добавило бы некоторые накладные расходы на каждую итерацию (ветвление).

РЕДАКТИРОВАТЬ: На самом деле, это не сработало бы, поскольку только один поток будет вызывать эти функции. Вам нужно будет определить некоторые локальные флаги потока и проверять их на итерациях. Тот же недостаток.

Гораздо лучшей альтернативой было бы просто разделить блоки кода parallel и for OpenMP:

 #pragma omp parallel
{
  api_start();

  #pragma omp for
  for (auto i = 0; i < count; i  )
  {
    api_process(i);
  }

  api_stop();
}