OpenMP如何平行这些循环

How does openMP parallelize these loops?

本文关键字:循环 何平 OpenMP      更新时间:2023-10-16

假设我有这些循环:

#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是如何并行运行的,以便我可以优化它们?

我的代码应在Windows(Visual Studio)和Arm Linux上运行。

而无需启用嵌套(环境变量OMP_NESTED = true),只有外圈才能并行运行。

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

您可以在外循环上使用OMP并行,并在内部循环上使用多个迭代的任务,例如:

#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-inpogram-using-openmp40中,您会找到一个使用#pragma omp parallel for simd的示例。这意味着并行化循环,每个线程将在应用矢量化的情况下运行其迭代空间。这仍将要求启用并行区域的嵌套(OMP_NESTED),并且根据运行时实现,它可以生成多个线程团队,每个线程的每个线程最多一个。

我同意实验是学习并行编程的好方法,您应该尝试多种组合(仅内部,仅外在,两者,其他东西?),看看什么是最好的对于您的代码。我的其余答案有望给您一个暗示为什么最快的方法是最快的。

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

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