5

配列を列優先の順序で格納する言語を使用していると仮定します。また、2次元配列を引数として使用し、それを返す関数があるとします。行単位の操作ではなく列単位の操作を処理するために関数を呼び出すときにこの配列を転置することが一般的に有益である(またはそうでない)と主張できますか、または転置は列単位の操作の利点は?

y例として、RIには、次元を持つ名前のクラスtsのオブジェクトがあります。n x pつまりp、長さの時系列がありnます。

私はFortranでいくつかの計算を行う必要がありyます。ここでは、次の種類の構造を持つ2つのループがあります。

do i = 1, n
  do j= 1, p
   !just an example, some row-wise operations  on `y`
   x(i,j) = a*y(i,j) 
   D = ddot(m,y(i,1:p),1,b,1) 
   ! ...
  end do
end do

Fortranは(Rと同様に)列単位のストレージを使用するため、p x n代わりに配列を使用して計算を行う方が適切です。だから代わりに

out<-.Fortran("something",y=array(y,dim(y)),x=array(0,dim(y)))
ynew<-out$out$y
x<-out$out$x

使用できます

out<-.Fortran("something2",y=t(array(y,dim(y))),x=array(0,dim(y)[2:1]))
ynew<-t(out$out$y)
x<-t(out$out$x)

ここで、Fortranサブルーチンsomething2は次のようになります。

do i = 1, n
  do j= 1, p
   !just an example, some column-wise operations  on `y`
   x(j,i) = a*y(j,i) 
   D = ddot(m,y(1:p,i),1,b,1) 
   ! ...
  end do
end do

nアプローチの選択は常にディメンションに依存しますpか、または計算速度やメモリ要件の観点から1つのアプローチの方が優れていると言えますか?私のアプリケーションnでは、通常、よりもはるかに大きくp、ほとんどの場合1〜10です。

4

1 に答える 1

3

コメントの詳細、購入私は少しコードを入れたかった:古い学校のf77の下では、基本的に2番目のアプローチを使用することを余儀なくされます

y(1:p,i)

は単にy(1、i)へのポインタであり、次のp値がメモリ内で連続しています。

最初の構成

y(i,1:p)

はメモリ内に配置された値のリストであるため、サブルーチンに渡すためにデータのコピーを作成する必要があるようです。現代の最適化コンパイラがこれらのことをどのように処理するかについて、私は最も曖昧な考えを持っていないためだと思います。せいぜい、最悪の場合、これは本当に傷つく可能性があると思う傾向があります。ベクトル全体にアクセスするにはページスワップが必要なほど大きな配列を想像してみてください。

結局、これに答える唯一の方法は、自分でテストすることです。

----------編集は少しテストを行い、私の予感を確認しました。行を渡すと、列y(i,1:p)を渡すよりもコストがかかりますy(1:p,i)。違いを確認するために、実質的に何もしないサブルーチンを使用しました。実際のサブルーチンでの私の推測では、ヒットは無視できます。

ところで(そしておそらくこれは何が起こっているのかを理解するのに役立ちます)列の他のすべての値を渡します

y(1:p:2,i)列全体を渡すよりも時間がかかります(桁違い)が、行に1つおきの値を渡すと、行全体を渡すよりも時間が半分になります。

(gfortran 12 ..を使用)

于 2013-03-02T14:49:08.357 に答える