Директивы OpenMP C ++ для параллельного цикла for? - PullRequest
0 голосов
/ 06 октября 2011

Я пытаюсь использовать OpenMP для определенного фрагмента кода.Не уверен, что фрагмент нуждается в обновлении, возможно, он настроен слишком жестко для последовательной реализации.В любом случае вот (псевдо) код, который я пытаюсь распараллелить:

#pragma omp parallel for private(id, local_info, current_local_cell_id, local_subdomain_size) shared(cells, current_global_cell_id, global_id)
for(id = 0; id < grid_size; ++id) {
   local_info = cells.get_local_subdomain_info(id);
   local_subdomain_size = local_info.size();
   ...do other stuff...
   do {
      current_local_cell_id = cells.get_subdomain_cell_id(id);
      global_id.set(id, current_global_cell_id + current_local_cell_id);
   } while(id < local_subdomain_size && ++id);
   current_global_cell_id += local_subdomain_size;
}

Это имеет полный смысл (после того, как на него какое-то время смотрят) в последовательном смысле, что также может означать, что оннужно переписать для OpenMP.Меня беспокоит то, что current_local_cell_id и local_subdomain_size являются частными, но current_global_cell_id и global_id являются общими.

Следовательно, выражение current_global_cell_id + = local_subdomain_size после внутреннего цикла:

do {
  ...
} while(...)
current_global_cell_id += local_subdomain_size;

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

Ответы [ 2 ]

2 голосов
/ 06 октября 2011

Я не уверен, что понимаю ваш код. Тем не менее, я думаю, что вы действительно хотите какое-то параллельное накопление.

Вы можете использовать шаблон как

 size_t total = 0;
 #pragma omp parallel for shared(total) reduction (+:total)
 for (int i=0; i<MAXITEMS; i++)
 {
      total += getvalue(i); // TODO replace with your logic
 }

 // total has been 'magically' combined by OMP

В связанной заметке, когда вы используете gcc, вы можете просто использовать замену __gnu_parallel::accumulate для std::accumulate, что делает exactly тем же. См. Глава 18. Параллельный режим

 size_t total = __gnu_parallel::accumulate(c.begin(), c.end(), 0, &myvalue_accum);

Вы даже можете скомпилировать с -D_GLIBCXX_PARALLEL, что позволит использовать все алгоритмы std автоматически распараллеливаясь, если это возможно. Не используйте это, если не знаете, что делаете! Зачастую производительность просто страдает, и вероятность появления ошибок из-за неожиданного параллелизма реальна

1 голос
/ 06 октября 2011

изменение идентификатора внутри цикла неверно.Невозможно передать цикл другому потоку, поскольку шаг цикла не создает предсказуемого значения идентификатора.

Почему вы используете id внутри цикла while?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...