在fortran中使用数组表示法替换do循环

时间:2013-10-09 13:33:18

标签: fortran fortran90

我想用FORTRAN的内部函数和数组符号替换下面的do循环。

do i=2, n
  do j=2, n
     a=b(j)-b(j-1)
     c(i,j)=a*c(i-1,j)+d(i,j)
   end do
end do

然而,由于c(i,j)取决于c(i-1,j),以下试验均无效。因为他们不更新c(i,j)

!FORALL(i = 2:n , j = 2:n ) c(i,j)=c(i-1,j)*(b(j)-b(j-1))+d(i,j)
!FORALL(i = 2:n) c(i,2:n)=c(i-1,2:n)*(b(2:n)-b(1:n-1))+d(i,2:n)
!c(2:n,2:n)=RESHAPE(   (/(c(i-1,2:n)*(b(2:n)-b(1:n-1))+d(i,2:n),i=2,n)/), (/n-1, n-1/))
!c(2:n,2:n)=RESHAPE((/(((b(j)-b(j-1)) *c(i-1,j)+d(i,j)  ,j=2,n),i=2,n)/), (/n-1, n-1/))
!c(2:n,2:n)=spread(b(2:n)-b(1:n-1),ncopies = n-1,dim=1) * c(1:n-1,2:n) +d(2:n,2:n)

这是我能得到的最好的。但它仍然有一个循环

do i=2, n
     c(i,2:n)=c(i-1,2:n)*(b(2:n)-b(1:n-1))+d(i,2:n)
end do

所有do循环都可以被内部函数和数组表示法替换。或者可以用某种方式替换这个?

2 个答案:

答案 0 :(得分:0)

根据我的经验,没有什么比传统的循环更好。所有扩展内在函数通过将内容复制到临时空间(通常在堆栈上),重新整形和排序来创建内存和CPU开销。如果您正在操作大型数组,则可能会遇到内部函数的内存不足问题。

您最好的选择是坚持正确布局索引的二维循环:

do i=2, n
  e = c(1:n,i-1)
  do j=2, n
     a=b(j)-b(j-1)
     c(j,i)=a*e(j)+d(j,i)
   end do
end do

通过替换索引(并确保您的维度声明如下),您将节省内存分页。 c(j,i)和d(j,i)引用在列内存中的行,而c(j,i-1)将跨越列(并产生分页开销)。所以我们将它复制到一个临时的e阵列。

我认为这将是最快的......

答案 1 :(得分:0)

开始
do i=2, n
   do j=2, n
      a=b(j)-b(j-1)
      c(i,j)=a*c(i-1,j)+d(i,j)
   end do
end do

我们可以通过使用doSIZESPREAD来快速消除EOSHIFT循环:


res = SPREAD(b - EOSHIFT(b,-1),2,SIZE(c,2))*EOSHIFT(c,-1) + d

啊哈,事实证明我收到的错误(V1)是由于我使用RESHAPE而不是SPREAD。我在当前版本(V2)中修复了它并编译了&适用于ifortgfortran