如何将循环转换为向量赋值表示法

How to convert a loop into vector assignment notation

如何转换这样的循环:

Do i = 2,101
   a(i) = b(i)
   c(i-1) = d(i) + d(i-1)
   d(i) = e(i) + 12
Enddo

Fortran的矢量符号中?我们显然可以拆分循环,然后做类似

的事情
a(2:101) = b(2:101)

但最后两个语句相互依赖,因此不会真正起作用。

首先,仔细看看你的非矢量化循环。前几次迭代将如下所示:

a(2) = b(2)
c(1) = d(2) + d(1)
d(2) = e(2) + 12

a(3) = b(3)
c(2) = d(3) + d(2)
d(3) = e(3) + 12

a(4) = b(4)
c(3) = d(4) + d(3)
d(4) = e(4) + 12

除非 d 在代码的前面进行了初始化,否则这可能会导致不可预测的行为(具体来说,d(2) 用于在 d(2) 本身被初始化之前计算 c(1)已分配)。


编辑:post 的其余部分不正确,正如 High Performance Mark 指出的那样。我还是把它留在这里供参考。

注意c依赖于d,但是d不依赖于c。因此,您可以按如下方式重写代码:

a(2: 101) = b(2: 101)
d(2: 101) = e(2: 101) + 12
c(1: 100) = d(2: 101) + d(1: 100)

这与 mtrw 的回答非常相似,但请注意最后一行中的 + 而不是 -c 的索引。

通过写出循环的几次迭代有正确的想法。 cd 更新为:

c(1) = d(2) + d(1)
d(2) = e(2) + 12

c(2) = d(3) + d(2) = d(3) + e(2) + 12
d(3) = e(3) + 12

c(3) = d(4) + d(3) = d(4) + e(3) + 12
d(4) = e(4) + 12

因此,c的第N个值取决于dN+1st值,以及eNth值。我们可以将整个循环写成:

a(2:101) = b(2:101)
c(1) = d(2) + d(1)
c(2:100) = d(3:101) + e(2:100) + 12
d(2:101) = e(2:101) + 12

Do i = 2,101
   a(i) = b(i)
   c(i-1) = d(i) + d(i-1)
   d(i) = e(i) + 12
Enddo

a(2:101) = b(2:101)
c(1:100) = d(2:101) + d(1:100)
d(2:101) = e(2:101) + 12

如果这更快,我对此表示怀疑,并且就设计意图而言它可能更加模糊,因此矢量化可能并不总是最好的方法。

编辑 1

a(2:101) = b(2:101)
d(2:101) = e(2:101) + 12
c(1:100) = d(2:101) + d(1:100)

因为 d 仅依赖于 ec 依赖于 d。从上面的循环中 d(1) 需要更早定义。