Hatena::ブログ(Diary)

数値計算とかの備忘録(仮)

2012-02-09

Fortranでの配列の要素へのアクセス順序について


Fortran配列では列優先でメモリに格納されるそうだ。

Fortranの多次元配列は列優先 (Column Major) です。(C/C++言語では行優先)例えば3行4列の2次元整数配列は integer a(3,4) のように宣言され、メモリ上には以下の順番で数値が格納されます。

a(1,1)
a(2,1)
a(3,1)
a(1,2)
a(2,2)
a(3,2)
a(1,3)
a(2,3)
a(3,3)
a(1,4)
a(2,4)
a(3,4)
Fortran入門: 配列

ということで以下のプログラムを使って実際に比べてみた。使用したマシンはちょっと昔のiMac

program ArrayTest
    implicit none
    integer :: a(1000, 1000) = 0
    integer :: n = 1000
    real :: s = 0
    integer i, j, k
    do k = 1, 5000
        do j = 1, n
            do i = 1, n
                a(i, j) = j - i
                s =  a(i, j)
            end do
        end do
    end do
    print *, s

end program ArrayTest

program ArrayTest2
    implicit none
    integer :: a(1000, 1000) = 0
    integer :: n = 1000
    real :: s = 0
    integer i, j, k
    do k = 1, 5000
        do i = 1, n
            do j = 1, n
                a(i, j) = j - i
                s =  a(i, j)
            end do
        end do
    end do
    print *, s

end program ArrayTest2


2つとも1000×1000の2次元配列の端から端までアクセスするのを5000回繰り返すだけのプログラム。上のほうは列優先でアクセスし、下のほうは行優先でアクセスする。最後のprintは特に意味はない。ループが終わったことの目印になればいいかと思ったけど別にいらないような…

timeコマンドで時間を測った結果がこちら。

・列優先のほう

 0.

real    0m30.697s
user    0m30.297s
sys     0m0.070s

・行優先のほう

 0.

real    0m42.868s
user    0m42.522s
sys     0m0.145s

なるほど確かに列優先だ。


じゃあ3次元配列も同じような感じなのかしら?ってことで調べてみた。

program ArrayTest3D
    implicit none
    integer :: a(100, 100, 100) = 0
    integer :: n = 100
    real :: s = 0
    integer i, j, k, iter
    do iter = 1, 2000
        do k = 1, n
            do j = 1, n
                do i = 1, n
                    a(i, j, k) = k - j - i
                    s =  a(i, j, k)
                end do
            end do
        end do
    end do
    print *, s

end program ArrayTest3D

program ArrayTest3D2
    implicit none
    integer :: a(100, 100, 100) = 0
    integer :: n = 100
    real :: s = 0
    integer i, j, k, iter
    do iter = 1, 2000
        do i = 1, n
            do j = 1, n
                do k = 1, n
                    a(i, j, k) = k - j - i
                    s =  a(i, j, k)
                end do
            end do
        end do
    end do
    print *, s

end program ArrayTest3D2


上のほうが列優先で、下のほうが行優先。i,j,kの組み合わせはほかにもあるけどとりあえずこの2つでやってみた。

結果はこちら。

・列優先のほう

 -100.

real    0m30.861s
user    0m30.845s
sys     0m0.012s

・行優先のほう

 -100.

real    0m34.517s
user    0m34.498s
sys     0m0.012s

2次元配列の時ほどではないけど、上のほうが速いことがわかる。
上のほうでのアクセス順序がi,j,kの組み合わせの中で一番速いのかな?

ということで、Fortran配列をループで扱うときはアクセスする順番に気を付けましょうというお話でした…

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/aldente39/20120209/1328800255
リンク元