如何将循环转换为向量赋值表示法
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
的索引。
通过写出循环的几次迭代有正确的想法。 c
和 d
更新为:
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个值取决于d
的N+1st
值,以及e
的Nth
值。我们可以将整个循环写成:
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
仅依赖于 e
而 c
依赖于 d
。从上面的循环中 d(1)
需要更早定义。
如何转换这样的循环:
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
的索引。
c
和 d
更新为:
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个值取决于d
的N+1st
值,以及e
的Nth
值。我们可以将整个循环写成:
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
仅依赖于 e
而 c
依赖于 d
。从上面的循环中 d(1)
需要更早定义。