Итак, на SO и в Интернетах в целом существует много путаницы и разочарования в отношении того, как сделать простые в использовании директивы #pragma
OpenMP совместимыми с С++ одинаково удобными контейнерами STL.
Все говорят об обходах для STL vector
, но как насчет контейнеров с неважным доступом/двунаправленности, таких как map
, list
, set
и т.д.?
Я столкнулся с этой проблемой и разработал очень простой, очевидный способ обхода. Я представляю его здесь для STL map
, но он явно обобщается.
Последовательная версия:
for (std::map<A,B>::iterator it = my_map.begin();
it != my_map.end();
++it)
{ /* do work with it */ }
Мое предлагаемое решение для использования OpenMP с STL map
:
//make an array of iterators.
int loop_length = my_map.size();
std::map<A,B>::iterator loop_array[ loop_length ];
std::map<A,B>::iterator allocate_it = my_map.begin();
for (int j=0; j<loop_length; ++j)
loop_array[j] = allocate_it++;
// now you can use OpenMP as usual:
#pragma omp parallel for
for (uint j=0; j<loop_length; ++j)
{ /* do work with loop_array[j] */ }
Я далек от эксперта по OpenMP, поэтому Я хотел бы знать, эффективна ли моя предлагаемая рабочая обстановка и хорошая практика.
Предположим, что программист отвечает за потокобезопасную обработку контейнера STL в цикле for.
Наконец, мое предложенное решение более эффективно, чем следующее общепринятое решение (см. ответ на этот вопрос SO), потому что в моем решении каждый поток не перебирать весь контейнер?
#pragma omp parallel
{
for (std::map<A,B>::iterator it = my_map.begin();
it != my_map.end();
++it)
#pragma single nowait
{ /* do work */ }
}