いつものようにNAGFortranのページでFortran Tipsを読み返していたらこんなページを見つけたので、実際に確かめてみました。三次元配列同士の積を、配列の大きさを50-1000まで変えて計算しました。
190801 コードを一部修正しました。
コード
cal_array.f90
program main
implicit none
integer :: i,j,k,n
real(kind=8),allocatable :: a(:,:,:) , b(:,:,:)
real(kind=8) :: t1,t2,s1,s2
do n = 50,1000,25
allocate(a(n,n,n))
allocate(b(n,n,n))
call random_number(a)
call random_number(b)
!----------- right -----------!
call cpu_time(t1)
do i = 1,n
do j = 1,n
do k = 1,n
a(i,j,k) = a(i,j,k) * b(i,j,k)
end do
end do
end do
call cpu_time(t2)
!----------- right -----------!
!----------- left-----------!
call cpu_time(s1)
do i = 1,n
do j = 1,n
do k = 1,n
a(k,j,i) = a(k,j,i) * b(k,j,i)
end do
end do
end do
call cpu_time(s2)
!----------- left -----------!
print*, n, t2-t1, s2-s1
deallocate(a)
deallocate(b)
end do
end program main
結果
ノイズを減らすために、実際には5回計算を行い算術平均を取っています。
配列の大きさが500を超えたあたりから右側からアクセスした場合の計算時間が大幅に増加しています。一方で左側からアクセスした場合は緩やかにしか変化していません。
小さい配列しか扱わなければそこまで気にしなくても良いのかもしれませんが、大規模な計算をする場合、配列のアクセス順序によって計算時間のパフォーマンスが目に見えて変わりうるという結果になりました。
余談
N=1000の計算だとメモリが16GB前後必要でした。実行される際はお気をつけて…。