如何告诉编译器可以安全地并行化循环?
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
【讨论】:
以上是关于如何告诉编译器可以安全地并行化循环?的主要内容,如果未能解决你的问题,请参考以下文章