- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我从 Fortran 的角度写了这个问题,但这些问题并不仅限于 Fortran(因此有 c++ 标签)。
我有两个问题。我读到在 OpenMP 并行循环的开始和停止时存在延迟 here .我的问题是:
Q1) 有哪些实用措施可以缓解 openMP 延迟?
Q2)以下哪种方法效果更好?
方法一
x = 1.0; y = 2.0
!$OMP PARALLEL DO
do k=1,Nz; do j=1,Ny; do i=1,Nx
x(i,j,k) = x(i,j,k)+y(i,j,k)
enddo; enddo; enddo
!$OMP END PARALLEL DO
!$OMP PARALLEL DO
do k=1,Nz; do j=1,Ny; do i=1,Nx
x(i,j,k) = x(i,j,k)*y(i,j,k)
enddo; enddo; enddo
!$OMP END PARALLEL DO
! (x should = 6.0 at this point)
方法二
x = 1.0; y = 2.0
!$OMP PARALLEL DO
do k=1,Nz; do j=1,Ny; do i=1,Nx
x(i,j,k) = x(i,j,k)+y(i,j,k)
x(i,j,k) = x(i,j,k)*y(i,j,k)
enddo; enddo; enddo
!$OMP END PARALLEL DO
! (x should = 6.0 at this point)
方法三
1) 创建一个包含过程数组的对象
2)调用数组过程如下
x = 1.0; y = 2.0
!$OMP PARALLEL DO
do k=1,Nz; do j=1,Ny; do i=1,Nx
do t=1,procedure_array%N
call procedure_array%single_procedure(t)%P(x(i,j,k),y(i,j,k))
enddo
enddo; enddo; enddo
!$OMP END PARALLEL DO
! (x should = 6.0 at this point)
假设 procedure_array%N = 2
和
procedure_array%single_procedure(1)
procedure_array%single_procedure(2)
指向子例程add
(x=x+y
) 和multiply
(x=x*y
) 分别。
3)清理(解除分配)
评论
首先,很明显方法 2 优于方法 1,因此我对方法 2 与方法 3 的比较很感兴趣。其次,我知道“试试看”是一个有效的答案,但是我想知道是否有方法 3 在实践(或行业)中使用的具体示例,或者方法 3 与方法 2 相比不如方法 2 的概念原因(例如,由于许多过程调用而导致的开销)。最后,如果可以采取某种特殊措施(例如,通过专门指定特定线程)使方法 2 和 3 几乎等效,它们是什么?
感谢您的帮助!
更新
根据评论,我做了以下更正。
感谢@innoSPG,关于缓存内存(和缓存故障)的回答非常有用!
澄清
最后,从评论中,我意识到这个问题的重点实际上是关于过程调用的,与 openmp 并行化没有严格的关系。也就是说,我保留了 openmp 语句,因为那是我更复杂的应用程序中发生的事情,我想尽可能多地保留它。从@Chaosit 的评论看来,过程调用将需要开销,从而减慢方法 3。有什么办法可以解决这个问题吗?
另外,如果我错了,请纠正我,但我相信方法 2 中的两个操作将按书面顺序执行,从而产生正确的最终 x
值。
最佳答案
我的理解是您正在寻找的差异(方法 2 和方法 3)不依赖于并行化。
让我解释一下:
由于方法 2 中不存在的过程调用,方法 3 可能会产生其他开销。我这么说可能是因为我不熟悉过程指针,但是,我的猜测是编译器的优化不会内联如果您使用过程指针,则过程调用。
由于过程调用而产生的开销完全独立于并行化。您仍将在顺序代码中拥有它。它不是并行化延迟的一部分。
现在,我冒着风险回到你不喜欢的选项:试试看。我冒这个风险是因为我相信你所展示的只是你问题的一个例证,你的实际情况更复杂。当您处理复杂的情况时,您可能会惊讶于方法 1 和方法 2 之间的结论不再有效。它可能在很大程度上取决于您手头的问题。一种情况的结论不适用于另一种情况。像现在的编译器一样聪明,他们不会捕获一切。在计算机科学中,缓存内存的概念有时并没有被很好地理解,但我不会详细介绍。您可能会遇到这样一种情况,方法 1 的每个单个循环(数据和/或代码)都保存在缓存中,而情况 2 的组合循环不保存在缓存中。简单的说明是方法 2 在内循环中遇到缓存故障而方法 1 没有的情况。在这种情况下,您会发现对于大循环边界,方法 1 远远优于方法 2。
这就是尝试看看
成为标准的地方,这也是现实生活中大多数情况下发生的情况。
关于c++ - 减轻 openmp 并行延迟的措施,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39579057/
OpenMP 中的高斯消除。我是 openmp 的新手,想知道我是否在正确的地方使用了我的编译指示和屏障。我的 x 值每次都不同。他们应该是一样的吗?? #include int num; doub
给定一个示例函数(示例在下面给出),for 循环可以使用 OpenMP 并行化或使用矢量化进行矢量化(假设编译器执行矢量化)。 示例 void function(float* a, float* b,
OpenMP 中原子和关键之间有什么区别? 我能做到 #pragma omp atomic g_qCount++; 但这和不一样吗 #pragma omp critical g_qCount++; ?
我有一个关于如何在您考虑特定依赖关系图时生成 OpenMP 伪代码的问题。 所以假设我们有这个特定的图表: 解决方案可能是这样的: #pragma omp parallel {
我正在尝试使用 openmp 计算二维矩阵的平均值。这个二维矩阵实际上是一个图像。 我正在对数据进行线程分割。例如,如果我有 N线程比我处理行/N thread0 的行数, 等等。 我的问题是:我可以
我想统计测量与 OpenMP 并行化的程序的性能。我选择在执行并行算法的测试应用程序中编写循环 MAX_EXPERIMENTS次并将时间测量报告到文件中。 问题解决方案似乎比提取外部循环上方的并行编译
我找到了 Intel's performance suggestion on Xeon Phi关于 OpenMP 中的 Collapse 子句。 #pragma omp parallel for co
如何使用 OpenMP 并行化数组移位? 我尝试了一些方法,但在以下示例中没有得到任何准确的结果(该示例旋转 Carteira 对象数组的元素,用于排列算法): void rotaciona(int
我有一系列对几个独立函数的调用。 func1(arg); func2(arg); func3(arg); 我想并行执行它们,而不是串行执行它们。我目前正在使用 #pragma omp parallel
我正在尝试使用 openmp 任务来安排基本 jacobi2d 计算的平铺执行。在 jacobi2d 中,依赖于 A(i,j) 从 A(i, j) A(i-1, j) A(i+1, j) A(i, j
我在 3 天前开始使用 OpenMP。我想知道如何使用#pragma使每个内核运行一个线程。详细信息:- int ncores = omp_get_num_procs();for(i = 0; i <
我有一段代码(它是应用程序的一部分),我正在尝试使用 OpenMP 对其进行优化,正在尝试各种调度策略。就我而言,我注意到 schedule(RUNTIME)条款比其他条款有优势(我没有指定 chun
我有一个数字运算 C/C++ 应用程序。它基本上是不同数据集的主循环。我们可以使用 openmp 和 mpi 访问一个 100 节点的集群。我想加速应用程序,但我是 mpi 和 openmp 的绝对新
在 OpenMP 中使用ompsections时,线程会被分配到sections内的 block ,还是每个线程会被分配到每个section? 当nthreads == 3时: #pragma omp
我正在尝试在 cython 中使用 openmp。我需要在 cython 中做两件事: i) 在我的 cython 代码中使用 #pragma omp single{} 作用域。 ii) 使用#pra
我正在尝试通过将循环的每次迭代作为 OpenMP 部分来并行化 OpenMP 中基于范围的 for 循环。我想这样做: #pragma omp parallel sections { for ( au
我正在尝试在 cython 中使用 openmp。我需要在 cython 中做两件事: i) 在我的 cython 代码中使用 #pragma omp single{} 作用域。 ii) 使用#pra
我想编写一个代码转换器,它采用基于 OpenMP 的并行程序并在集群上运行它。 我该如何解决这个问题?我使用哪些库?如何为此设置小型集群? 我发现很难在 Internet 上找到有关集群计算的好 Ma
我是 OpenMP 的新手。我正在尝试为 for 循环使用多个内核,但出现此编译错误: “错误 C3016:'x':OpenMP 'for' 语句中的索引变量必须具有带符号的整数类型”。 我知道 Op
如果我使用 VS 2010 编译器从 Qt Creator 构建项目,我如何启用 OpenMP(从 Visual Studio 构建时,您只需启用该功能)谢谢 最佳答案 在 .pro 文件中尝试下一步
我是一名优秀的程序员,十分优秀!