Правильный способ распараллеливания циклов в OpenMP в Visual Studio, когда параллельные потоки обращаются к другому члену одной и той же структуры данных? - PullRequest
0 голосов
/ 01 мая 2019

Я написал программу с интенсивными вычислениями, которая запускается последовательно на обычном терминале, но занимает около 30 с на одну итерацию моего цикла.Я решил запустить свой код с OpenMP в Visual Studio с компилятором Intel, чтобы распараллелить циклы for в нем.Во-первых, тот же последовательный код, который занимает 30 с на итерацию, занимает 600 с на итерацию в Visual Studio с компилятором Intel по сравнению с обычным компилятором G ++ на обычном терминале.Во-вторых, даже при реализации параллельных циклов для кода выполнение одной итерации занимает примерно одинаковое время.Я приложил упрощенную версию кода ниже.Меня беспокоит состояние гонки, поскольку распараллеленные циклы обращаются к одной и той же неупорядоченной карте и читают и записывают с нее, но никакие два потока никогда не обращаются к одному и тому же элементу.

Я пытался использовать оба решения, упомянутые в этой теме SO, сегменты для неупорядоченной карты, а также задачу #pragma omp.Оба дают мне одинаковое время исполнения. OpenMP / __ gnu_parallel для unordered_map

unordered_map <int, Cluster*> cluster_map;
while(true)
{
   #pragma omp parallel
   {
      #pragma omp for schedule(dynamic, bc/4)
      for (unsigned b = 0; b<bc; ++b)
      {
     for (auto c = clusters.begin(b); c != clusters.end(b); ++c)
     {
         //Computations involving the current cluster
         }
      }
   }
}

В целом, я предполагаю, что проблема связана с Visual Studio, но, поскольку я новичок в OpenMP, она также может быть с моим кодом.В свойствах моего проекта установлено использование компилятора Intel, и включена поддержка OpenMP.

1 Ответ

0 голосов
/ 01 мая 2019

Вы можете просто реструктурировать код, используя контейнер, который поддерживает произвольный доступ:

std::unordered_map <int, Cluster*> cluster_map;
while(true)
{

   std::vector< std::pair<int, Cluster*> > cluster_vec(cluster_map.begin(), cluster_map.end());
   #pragma omp parallel for
   for(int i = 0; i < cluster_vec.size(); ++i)
   {
     //Computations involving the current cluster
   }

}
...