我正在尝试特定代码段上的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循环,我将不胜感激。
答案 0 :(得分:2)
我不确定我理解你的代码。但是,我认为你真的想要某种并行积累。
你可以使用像
这样的模式 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
的{{1}}替代品替换std::accumulate
,exactly
相同。见Chapter 18. Parallel Mode
size_t total = __gnu_parallel::accumulate(c.begin(), c.end(), 0, &myvalue_accum);
您甚至可以使用-D_GLIBCXX_PARALLEL
进行编译,如果可能的话,这将使std
算法的所有使用自动并行化。 除非你知道自己在做什么,否则不要使用它!通常,性能会受到影响,并且由于意外的并行性而引入错误的可能性是真实的
答案 1 :(得分:1)
更改循环内的id是不正确的。没有办法将循环调度到不同的线程,因为循环步骤不会产生可预测的id值。
为什么你在while循环中使用id?