Openmp omp并行与omp并行

Openmp omp并行与omp并行,openmp,Openmp,这两者有什么区别 [A] #pragma omp并行 { #pragma omp for 对于(int i=1;i

这两者有什么区别

[A]

#pragma omp并行
{ 
#pragma omp for
对于(int i=1;i<100;++i)
{
...
}
}
[乙]

#pragma omp parallel for
对于(int i=1;i<100;++i)
{
...
}

我不认为有什么区别,一个是另一个的捷径。尽管您的具体实现可能会以不同的方式处理它们

组合的并行工作共享构件是 指定包含一个工作共享构件的并行构件 没有其他声明。允许条款是这些条款的结合 允许并行和工作共享施工

取自

OpenMP的规格如下所示:

这些是等效的


#pragma omp parallel
生成一组线程,而
#pragma omp for
在生成的线程之间划分循环迭代。您可以使用fused
#pragma omp parallel for
指令同时完成这两件事。

在g++4.7.0中使用for循环时,我看到了截然不同的运行时 和使用

std::vector<double> x;
std::vector<double> y;
std::vector<double> prod;

for (int i = 0; i < 5000000; i++)
{
   double r1 = ((double)rand() / double(RAND_MAX)) * 5;
   double r2 = ((double)rand() / double(RAND_MAX)) * 5;
   x.push_back(r1);
   y.push_back(r2);
}

int sz = x.size();

#pragma omp parallel for

for (int i = 0; i< sz; i++)
   prod[i] = x[i] * y[i];
std::向量x;
std::向量y;
std::向量prod;
对于(int i=0;i<5000000;i++)
{
double r1=((双)rand()/double(rand_MAX))*5;
双r2=((双)兰德()/双(兰德最大值))*5;
x、 推回(r1);
y、 推回(r2);
}
int sz=x.size();
#pragma-omp并行
对于(int i=0;i
串行代码(无
openmp
)运行79毫秒。 “parallel for”代码运行时间为29毫秒。 如果我省略
,并使用
#pragma omp parallel
,则运行时将达到179ms, 这比串行代码慢。(机器的hw并发性为8)


代码链接到
libgomp

,这里是使用分离的
并行
的示例。简而言之,它可以用于在多个线程中执行
for
cycle之前动态分配OpenMP线程专用阵列。 对于
情况,不可能在
并行中执行相同的初始化

UPD: 在问题示例中,单个pragma和两个pragma之间没有区别。但在实践中,您可以使用分离的并行和for指令来实现更多的线程感知行为。 一些代码,例如:

#pragma omp parallel
{ 
    double *data = (double*)malloc(...); // this data is thread private

    #pragma omp for
    for(1...100) // first parallelized cycle
    {
    }

    #pragma omp single 
    {} // make some single thread processing

    #pragma omp for // second parallelized cycle
    for(1...100)
    {
    }

    #pragma omp single 
    {} // make some single thread processing again

    free(data); // free thread private data
}

尽管具体示例的两个版本是等效的,正如其他答案中已经提到的,但它们之间仍然有一个小的区别。第一个版本包括“omp for”结尾处遇到的不必要的隐式障碍。另一个隐式势垒位于平行区域的末端。至少从OpenMP的角度来看,将“nowait”添加到“omp for”将使这两个代码等效。我之所以提到这一点,是因为OpenMP编译器可以为这两种情况生成稍有不同的代码。

显然有很多答案,但这一个答案很好地解决了这一问题(源代码)

#pragma omp for
仅为 当前团队中的不同线程。团队是线程组 执行程序。在项目开始时,团队仅由一名 单个成员:运行程序的主线程

要创建新的线程组,需要指定并行线程 关键词。可以在周围的上下文中指定:

#pragma omp parallel
{
   #pragma omp for
   for(int n = 0; n < 10; ++n)
   printf(" %d", n);
}
#pragma omp并行
{
#pragma omp for
对于(int n=0;n<10;++n)
printf(“%d”,n);
}
以及:

什么是:平行,为和一个团队 平行线之间的区别, 与之平行的如下所示:

团队是一组线程 当前正在执行的。在项目开始时,团队由以下人员组成: 一根线。并行构造将当前线程拆分为 下一个块/语句期间的新线程组, 之后,团队合并为一个团队。因为他把工作分成两部分 在当前团队的线程之间进行for循环

它不会创建 线程,它只在当前 执行团队。parallel for是同时表示两个命令的缩写: 平行和平行。Parallel创建了一个新团队,对于拆分 团队负责处理循环的不同部分。如果你的程序从来没有 包含一个并行构造,没有多个线程; 启动并运行程序的主线程,如中所示 非线程程序


TL;DR:唯一的区别是第一个代码调用两个隐式屏障,而第二个代码只调用一个


参考官方OpenMP 5.1标准的更详细答案。

#pragma omp parallel

将创建一个
并行区域
,其中包含一组
线程
,每个线程将执行
并行区域
包含的整个代码块

从中可以看到更正式的描述:

当一个线程遇到一个并行构造时,一个线程组被激活 创建以执行并行区域(..)。这个 遇到并行构造的线程成为主线程 新团队的线程,在持续时间内线程数为零 新的平行区域新团队中的所有线程,包括 主线程,执行区域。创建团队后 团队中的线程数在任务期间保持不变 平行区域

委员会:

#pragma omp parallel for

将创建一个
并行区域
(如前所述),并将使用
默认块大小
默认调度
(通常为
静态
)为该区域的
线程
分配它所包含的循环迭代。忍受
#pragma omp parallel
{ 
    double *data = (double*)malloc(...); // this data is thread private

    #pragma omp for
    for(1...100) // first parallelized cycle
    {
    }

    #pragma omp single 
    {} // make some single thread processing

    #pragma omp for // second parallelized cycle
    for(1...100)
    {
    }

    #pragma omp single 
    {} // make some single thread processing again

    free(data); // free thread private data
}
#pragma omp parallel
{
   #pragma omp for
   for(int n = 0; n < 10; ++n)
   printf(" %d", n);
}
for(int i=omp_get_thread_num(); i < n; i+=omp_get_num_threads())
{  
    //...
}