openMP如何并行化这些循环?

时间:2015-05-07 12:38:39

标签: c++ parallel-processing openmp

假设我有这些循环:

#pragma omp parallel for
   for(int i=0;i<100;++i)
   { 
        // some big code here
#pragma omp parallel for
        for(int j=0;j<200;j++)
        {
            // some small code here
        }
    }

哪个循环并行运行?哪一个最好并行运行?

这里的要点是:

1-如果i-loop并行运行,因为那里有一些大代码,很有可能CPU缓存在循环的每次迭代中都会命中。

2-如果j-loop并行运行,因为那里没有太多代码,它可能没有达到CPU缓存,但我正在失去并行运行大代码。

我不知道openMP如何并行运行这些for循环所以我可以优化它们?

我的代码应该在windows(visual studio)和ARM Linux上运行。

2 个答案:

答案 0 :(得分:1)

如果不启用嵌套(环境变量OMP_NESTED = true),则只有外部循环并行运行。

如果启用嵌套,则两个循环将并行运行,但可能会创建太多线程。

您可以在外部循环上使用omp parallel,并为内部循环使用任务分组多次迭代,例如:

#pragma omp parallel for
for (int i = 0; i<100; i++) {
    //big code here

    blocksize = 200/omp_get_num_threads();
    int j = 0;
    while(j < 200) {
        int mystart = j; int myend = j+(blocksize-1);
        #pragma omp task firstprivate(mystart,myend)
        {
            //small code here
        }
        if (j + blocksize >= 200) j = 200 - blocksize;
        else (j+=blocksize);
    }
    #pragma omp taskwait   
}

如果你考虑在内循环中使用SIMD,那么它的编写方式与你的内容完全相似:

#pragma omp parallel for
for (int i = 0; i<100; i++) {
    //big code here
    #pragma omp simd
    for (int j = 0; j<200; j++) {
        //small code here
    }   
}

但是这个最新的选项非常具体。基本上强制编译器对循环进行矢量化。

有关该主题的更多信息。在https://software.intel.com/en-us/articles/enabling-simd-in-program-using-openmp40中,您会找到一个使用#pragma omp parallel for simd的示例。这意味着并行化循环,每个线程将运行其迭代空间并应用矢量化。 这仍然需要启用并行区域的嵌套(OMP_NESTED),并且根据运行时实现,它可以生成多个线程组,每个线程的外部循环最多一个。

答案 1 :(得分:0)

我同意实验是学习并行编程的好方法,你应该尝试多种组合(仅内部,仅外部,两者,其他?),以查看代码的最佳组合。我的答案的其余部分将有希望给你一个提示,为什么最快的方式是最快的。

可以完成嵌套并行区域,但通常不是您想要的。考虑这个question进行类似的讨论。

当选择要并行化的循环时,常见的主题是首先将最外层循环并行化用于多核,并且最内层循环首先用于SIMD。当然有一些警告。并非所有循环都可以并行化,因此在这种情况下,您应该继续进行下一个循环。此外,局部性,负载平衡和错误共享可能会改变哪个循环是最佳的。