将for循环转换为OpenMP

时间:2013-11-25 03:42:06

标签: c++ openmp

所以我有一个循环,我迭代一个向量的元素,在每个元素上调用一个函数,如果它符合某个条件,我将它推到一个列表上。

my_list li;

for (auto itr = Obj.begin(); itr != Obj.end(); ++itr) { 
     if ((*itr).function_call()) 
         li.push_back((*itr);
}

我一直在考虑如何优化我的程序,我遇到了OpenMP,但很多示例代码很难理解。

有人可以指导我如何转换上述循环以并行使用多个核心吗?

感谢。

2 个答案:

答案 0 :(得分:1)

您需要注意并行化该代码段

  1. 如果您正在使用OpenMP 3.0(或更高版本),您可以并行化for循环#pragma omp for,如果您使用的是旧版本的OpenMP,则需要使用for循环访问带索引的向量
  2. 您需要使用锁定保护li.push_back((*itr);语句或将其设置为关键部分
  3. 如果function_call不是一个非常慢的函数或者你的向量不包含那么多项,那么可能没有必要并行化,因为线程创建会引入开销。
  4. 因此伪代码实现将是

    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的列表来优化他的代码)。让我列举提高效率的四种方法。

  1. 将容器装入关键区块的平行部分
  2. 为每个线程创建容器的私有版本,并行填充它们,然后将它们合并到关键部分
  3. 请勿使用STL容器。 STL的设计并未考虑效率。相反,要么自己编写,要么使用专为提高效率而设计的Agner Fog's containters。例如,不使用堆进行内存分配,而是使用内存池。
  4. 在某些特殊情况下,也可以并行合并容器的私有版本。
  5. 第一种情况的示例代码在接受的答案中给出。这违背了使用线程代码的大部分目的,因为每次迭代都会在关键部分填充容器。

    第二种情况的示例代码可以在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

    找到显示如何执行此操作的示例