如何告诉编译器可以安全地并行化循环?

Posted

技术标签:

【中文标题】如何告诉编译器可以安全地并行化循环?【英文标题】:how to tell the compiler that a loop can be safely parallelized? 【发布时间】:2016-11-28 00:01:09 【问题描述】:

我正在更新一个大数组中的一些元素。

更新包括:

    将当前值乘以十(如果它不为零) 清除当前值 将更新后的值移动到数组中的新位置

我知道移动发生时不会发生碰撞。 如何告诉编译器它可以安全地并行化循环?

do i = 1, 1e6
    if ( v[i] /= 0 ) then
        temp = v[i] * 10
        v[i] = 0
        ndx = get_move_to_ndx(i)
        v[ndx] = temp
    end if
end do

我正在使用 ifort,但我想这与编译器无关。

【问题讨论】:

什么是 Fortran 和 C 的奇怪混合...更不用说使用 DO 循环的真实结束值,这是一个已删除的功能(更不用说一个坏主意。)如果你使用 DO CONCURRENT 这将是编译器循环适合并行化的线索,但调用需要是 PURE 过程。如果您不介意特定于 ifort 的内容,那么 !DIR$ IVDEP 可能会有所帮助。 以上在我看来很像python 编译器不可能自动猜测不会有冲突。例如,如果您将 OpenMP 与共享数组一起使用,它应该可以正常工作。 一个应该快速完成的循环。你知道需要多长时间吗?最好先了解什么是足够好,或者它作为终点或起点的表现如何。 为您的编译器查找 fortran 指令。这里是英特尔编译器 ifort 指令的链接:software.intel.com/en-us/articles/… 【参考方案1】:

这是一种杂种方法,因此您对使用临时向量有一些想法。 WHERE 可能不正确,您必须尝试一下。 WHERE/ELSEWHERE 的主要优点是可读性,因为它通常不如循环快......只是更容易阅读。

!DIR$ SIMD
FillTemp: Do I = 1, 1000000
  Temps(I) = v(I)*10
ENDDO FillTemp

!$OMP PARALLEL DO
FindIndex: Do I = 1, 1000000
  ndx_vect(I) = get_move_to_ndx(i)
ENDDO FindIndex

WHERE( Temps /= 0 )
  V = 0
ELSEWHERE
  v(ndx_Vect) = tempz
ENDWHERE

【讨论】:

以上是关于如何告诉编译器可以安全地并行化循环?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 并行化库:OpenMP 与线程构建块 [关闭]

random_number()如何并行工作?

多面体编译技术与示例分析

如何告诉编译器展开这个循环[重复]

C++ OpenMP 和 gcc 4.8.1 - 并行化循环时的性能问题

我可以使用 OpenACC 并行化调用某些函数的大代码吗?