3

派生型の設計に関する具体的な情報を見つけるのに苦労しました。これについて議論する最善の方法は、いくつかのオプションを使用することだと思います。派生型のさまざまなアプリケーションを使用して、コードのいくつかのセクションを作成しました。npartsindex、およびには動的配列を使用したいと思いますrefs。構造体を実際に使用するコードのセクションは省略しましたが (私が作成したものなのでありません)、例を示し、ルーチンで構造体のすべての値を少なくとも 1 回は使用するつもりです。

オプション A:派生型で静的配列を使用します。欠点は、コンパイル時に配列のサイズを推測する必要があることです。

! Known before compile time.
nboxes = 5000
max_parts = 2000
packs = 10

Type Boxes
   Sequence
   Integer :: location, date
   Integer, Dimension(0:packs) :: nparts
   Integer, Dimension(max_parts,packs) :: index
   Real(Kind=8), Dimension(packs,packs) :: refs
End Type Boxes

type(boxes), dimension(:), allocatable :: assembly
allocate(assembly(nboxes))

! Perform some operations on assembly...
do i = 1,nboxes
   do j = 1,packs
      do k = j,packs
         example = assembly(i)%nparts(k) - assembly(i)%nparts(j)
         .
         .
         do m = 1,max_parts
            example = assembly(i)%index(m,j) + assembly(i)%refs(k,j) * assembly(i)%nparts(j)
            .
            .
         end do
      end do
   end do
end do

オプション B:派生型で動的配列を使用します。

! Defined during execution. Much better.
nboxes = 5000
max_parts = 2000
packs = 10

Type Boxes
   Sequence
   Integer :: location, date
   Integer, Dimension(:), Allocatable :: nparts
   Integer, Dimension(:,:), Allocatable :: index
   Real(Kind=8), Dimension(:,:), Allocatable :: refs
End Type Boxes

type(boxes), dimension(:), allocatable :: assembly
allocate(assembly(nboxes))
do i = 1,nboxes
   allocate(assembly(i)%nparts(0:packs))
   allocate(assembly(i)%index(max_parts,packs))
   allocate(assembly(i)%refs(packs,packs))
end do

! Perform some operations on assembly...
do i = 1,nboxes
   do j = 1,packs
      do k = j,packs
         example = assembly(i)%nparts(k) - assembly(i)%nparts(j)
         .
         .
         do m = 1,max_parts
            example = assembly(i)%index(m,j) + assembly(i)%refs(k,j) * assembly(i)%nparts(j)
            .
            .
         end do
      end do
   end do
end do

オプション C:派生型で使用される動的配列の数を最小限に抑え、強制的assemblyに配列にします。ただし、このバージョンでは未使用のメモリが大量にあることに注意してください。たとえば、npartsから の時間のindexメモリが必要です。packsassembly(packs,packs,nboxes)

! Defined during execution. Much better.
nboxes = 5000
max_parts = 2000
packs = 10

Type Boxes
   Sequence
   Integer :: location, date, nparts, index
   Real(Kind=8) :: refs
   Integer, Dimension(:), Allocatable :: index
End Type Boxes

type(boxes), dimension(:,:,:), allocatable :: assembly
allocate(assembly(packs,packs,nboxes))
do i = 1,nboxes
   do j = 1,packs
      do k = 1,packs
         allocate(assembly(k,j,i)%index(max_parts))
      end do
   end do
end do

! Perform some operations on assembly...
do i = 1,nboxes
   do j = 1,packs
      do k = j,packs
         example = assembly(k,j,i)%nparts - assembly(k,j,i)%nparts
         .
         do m = 1,max_parts
            example = assembly(k,j,i)%index(m) + assembly(k,j,i)%refs * assembly(k,j,i)%nparts
            .
            .
         end do
      end do
   end do
end do

オプション D:オプション C の別の順列。

質問:

  1. do示されているループ例の派生型を設計する正しい/予想される方法は、どのバージョンですか? 動的配列機能が必要な場合、どのバージョンが最も最適化されていますか?
  2. 上記に関連しているのかもしれません。メモリはどのように割り当てられ、アクセスされますか? の使用はSEQUENCE価値がありますか? とにかく、割り当てられた配列は順番に表示されないと思います。assemblyの各セクションが小さいため、これはオプション C が最適であることを示しているのではないでしょうか?
  3. この派生型を複数の派生型に分割するか、完全に削除して変数に固執する必要がありますか? この派生型を複数のルーチンで使用し、モジュールに配置します。
4

1 に答える 1