所以我有一个循环,我迭代一个向量的元素,在每个元素上调用一个函数,如果它符合某个条件,我将它推到一个列表上。
my_list li;
for (auto itr = Obj.begin(); itr != Obj.end(); ++itr) {
if ((*itr).function_call())
li.push_back((*itr);
}
我一直在考虑如何优化我的程序,我遇到了OpenMP,但很多示例代码很难理解。
有人可以指导我如何转换上述循环以并行使用多个核心吗?
感谢。
答案 0 :(得分:1)
您需要注意并行化该代码段
#pragma omp for
,如果您使用的是旧版本的OpenMP,则需要使用for循环访问带索引的向量li.push_back((*itr);
语句或将其设置为关键部分因此伪代码实现将是
my_list li; #pragma omp for for (auto itr = Obj.begin(); itr != Obj.end(); ++itr) { if ((*itr).function_call()) { #pragma omp critical CRIT_1 { li.push_back((*itr); } } }
答案 1 :(得分:0)
现在是讨论使用容器类的有效方法的时候了,比如使用OpenMP的std :: list或std :: vector(因为OP希望使用带有OpenMP的列表来优化他的代码)。让我列举提高效率的四种方法。
第一种情况的示例代码在接受的答案中给出。这违背了使用线程代码的大部分目的,因为每次迭代都会在关键部分填充容器。
第二种情况的示例代码可以在C++ OpenMP Parallel For Loop - Alternatives to std::vector找到。不是在这里重新发布代码,而是让我举一个使用Agner Fog容器类的第三种情况的例子
DynamicArray<int> vec;
#pragma omp parallel
{
DynamicArray<int> vec_private;
#pragma omp for nowait //fill vec_private in parallel
for(int i=0; i<100; i++) {
vec_private.Push(i);
}
//merging here is probably not optimal
//Dynamic array needs an append function
//vec should reserve a size equal to the sum of size each vec_private
//then use memcpy to append vec_private into vec in a critcal section
#pragma omp critical
{
for(int i=0; i<vec_private.GetNum(); i++) {
vec.Push(vec_private[i]);
}
}
}
最后,在特殊情况下,例如直方图(可能是实验粒子物理学中最常见的数据结构),也可以并行合并私有数组。对于直方图,这相当于数组缩减。这有点棘手。可以在Fill histograms (array reduction) in parallel with OpenMP without using a critical section
找到显示如何执行此操作的示例