微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenMP parallel for -- 多个并行 for 的 Vs一个并行,其中包含多个 for 的

如何解决OpenMP parallel for -- 多个并行 for 的 Vs一个并行,其中包含多个 for 的

我正在经历Using OpenMP。作者比较并对比了以下两种结构:

//Construct 1
#pragma omp parallel for
for( ... )
{
    /* Work sharing loop 1 */
}
...
#pragma omp parallel for
for( ... )
{
    /* Work sharing loop N */
}

反对

//Construct 2
#pragma omp parallel
{
    #pragma omp for    
    for( ... )
    {
        /* Work sharing loop 1 */
    }
    ...
    #pragma omp for    
    for( ... )
    {
        /* Work sharing loop N */
    }
}

他们声明构造 2

隐含障碍较少,可能有缓存的潜力 循环之间的数据重用。这种方法的缺点是 不能再在每个循环的基础上调整线程数,但是 这通常不是真正的限制。

我很难理解 Construct 2 如何减少隐含障碍。由于 #pragma omp for,在每个 for 循环之后,构造 2 中是否没有隐含的障碍?那么,在每种情况下,隐含障碍的数量是否相同,N?也就是说,在Construct 2中是不是先出现第一个循环,依此类推,然后最后执行N个for循环?

此外,Construct 2 如何更有利于循环之间的缓存重用?

解决方法

我很难理解 Construct 2 如何减少 隐含的障碍。在构造 2 之后是否没有隐含的障碍 每个for循环由于#pragma omp for?所以,在每种情况下,不是 隐含障碍的数量相同,N?也就是说,在 构造 2,第一个循环首先发生,依此类推,然后是 第 N 个 for 循环最后执行?

我没有读过这本书,但根据您所展示的内容,它实际上是相反的,即:

 //Construct 1
#pragma omp parallel for
for( ... )
{
    /* Work sharing loop 1 */
} // <-- implicit barrier 
...
#pragma omp parallel for
for( ... )
{
    /* Work sharing loop N */
} // <-- implicit barrier.

N个隐式障碍(在每个平行区域的末尾),而第二个代码:

 //Construct 2
#pragma omp parallel
{
    #pragma omp for    
    for( ... )
    {
        /* Work sharing loop 1 */
    } <-- implicit barrier
    ...
    #pragma omp for    
    for( ... )
    {
        /* Work sharing loop N */
    } <-- implicit barrier
} <-- implicit barrier

有 N+1 个障碍(在每个的末尾 + 平行区域)。

实际上,在这种情况下,由于最后两个隐式障碍之间没有计算,因此可以将nowait添加到最后一个#pragma omp for以消除其中一个冗余障碍。

第二个代码比第二个代码具有更少的隐式障碍的一种方法是,如果您将 nowait 子句添加到 #pragma omp for 子句中。

来自关于您所展示的图书的链接:

最后,使用 OpenMP 考虑了可能影响 OpenMP 的趋势 发展,提供对未来可能性的一瞥 OpenMP 3.0 从当前 OpenMP 2.5 的角度来看。与 多核计算机的使用越来越多,需要一个全面的 标准界面的介绍和概述清晰。

所以这本书使用的是 OpenMP 2.5 标准,从standard 关于loop 构造函数可以阅读:

在循环构造函数的末尾有一个隐式屏障 除非指定了 nowait 子句。

nowait 不能添加到 parallel 构造函数中,但可以添加到 for 构造函数中。因此,如果可以将 nowait 子句添加到 #pragma omp for 子句中,则第二个代码具有潜力具有更少的隐式障碍。但是,实际上,第二个代码实际上比第一个代码具有更多的隐式障碍。

此外,Construct 2 如何更有利于循环之间的缓存重用?

如果您在线程之间使用循环迭代的 static 分布(例如 #pragma omp for scheduler(static,...) 在第二个代码中,相同的线程将使用相同的循环迭代。例如,有两个线程让我们称它们为 Thread AThread B。如果我们假设 static 分布具有 chunk=1Thread AB 将分别使用每个循环的奇数和偶数迭代。因此,根据实际的应用程序代码,这可能意味着这些线程将使用给定数据结构的相同内存位置(例如, 相同的数组位置)。

在第一个代码中,理论上(但这将取决于具体的 OpenMP 实现),因为有两个不同的并行区域,不同的线程可以在两个循环中选择相同的循环迭代.换句话说,在我们使用两个线程的示例中,不能保证在一个循环中计算偶数(或奇数)的同一线程会在其他循环中计算相同的数字。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?