a1 = [1.0]
などの長さの異なる配列がたくさんありますa2 = [1.0,2.0]
。関数内のすべての配列をループして、それらの要素で操作を実行する必要がありますが、どれもインデックスの関数ではありません。Fortran 95 でこれを行う最善の方法は何でしょうか? (max_length, max_length)
次元の配列を作成し、それらをすべてその中に入れることができると思います。これにより、各要素をインデックスで参照できますが、スペースが無駄になり、個々の配列だけでなく、呼び出すたびに配列全体を関数に渡す必要があります(実際にそれがどうかはわかりません)重要ですが、そうなるようです。)
2 に答える
(maxlen, maxlen) の配列を持つことは、(数千、数千) について話している場合にのみ問題を引き起こします。それ以外の場合は、非効率的なアプローチです。
配列がすべて同じ型で同じ次元数であると仮定すると、配列を保持する派生型を作成し、作成したばかりの型の配列を作成できます。したがって、可変長の配列の配列が得られます。
type arrays
integer(kind=8):: length !optional but very helpfull
integer(kind=8), dimension(:), allocatable:: a
end type arrays
型配列の配列を宣言できるようになりました。
type(arrays), dimension(:), allocatable:: arrayList
type(arrays):: arrayList ( 1000 ) !if you know beforehand how many arrays you need
このアプローチには、次の 2 つの点に注意してください。
- 私の経験では、派生型の配列のループは、ネイティブ型の配列よりも遅くなります。
- 今、あなたはあなたのa1、a2にアクセスしますが、
arrayList(i) % a(j)
これは一見怖いかもしれません
ソース: http://courses.physics.illinois.edu/phys466/comp_info/derived.html
追加情報については、非常に優れた情報源であるFortran Wikiにアクセスしてください。
答えは、実際のケースによって異なります。さまざまな配列の長さが同じではないが、少なくとも同じ桁数である場合は、それらすべてに対して 1 つの配列を使用する方がよい場合があります。ただし、すべての配列の要素数を示す追加の配列が必要になります。関数は次のようになります。
module test
implicit none
integer, parameter :: dp = kind(1.0d0)
contains
subroutine process(array, nelems)
real(dp), intent(in) :: array(:,:)
integer, intent(in) :: nelems(:)
integer :: ii, jj
do ii = 1, size(arrays(dim=2))
do jj = 1, nelems(ii)
! Do something with element jj of array ii.
end do
end do
end subroutine process
end module test
ここで、サブ配列array(1:nelems(ii),ii)
には i 番目の 1D 配列の要素が格納されます。
次の点に注意してください。
サブ配列がメモリ内で連続するように、集合的な 2D 配列の列ごとに 1D サブ配列を配置する必要があります。
一連の配列ではなく、2 つの配列のみをサブルーチンに渡す必要があります。これにより、より明確なコードが得られるはずです。
もちろん、集団配列の形状は でなければならないので、いくらかのメモリを無駄にします
(max_nr_of_elements_in_an_array, number_of_arrays)
。配列の長さが非常に異なり、実際に多くの配列があるため、無駄なメモリが大きくなる場合は 、 Eudoardo によって提案されている配列の配列アプローチについて考えることができます。ただし、これは、個々の配列がメモリ内に散らばっているため (キャッシングの問題)、直接的なアプローチよりも遅くなることがよくあります。