1

以下の do ループを FORTRAN の組み込み関数と配列表記に置き換えたいと思います。

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ループがあります

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

ループを組み込み関数と配列表記に置き換えることはできますか。または、これを何らかの形で置き換えることができますか?

4

2 に答える 2

0

私の経験では、従来の do-loop に勝るものはありません。すべての拡張組み込み関数は、一時スペース (通常はスタック上) へのコピー、再形成、および並べ替えによって、メモリと CPU のオーバーヘッドを作成します。大きな配列を操作している場合、組み込み関数でメモリ不足の問題が発生する可能性があります。

最良のオプションは、インデックスが正しく配置された 2 次元ループに固執することです。

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 配列にコピーします。

これが一番早いと思います…。

于 2013-10-09T21:03:51.367 に答える
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

doと をうまく使うことで、ループをSIZEすばやくSPREADなくすことができEOSHIFTます。


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

あはは、私が受け取っていたエラー (V1) はRESHAPESPREAD. 現在のバージョン (V2) でこれを修正し、 と の両方でコンパイルおよび動作しifortますgfortran

于 2013-10-10T21:03:46.987 に答える