Я изо всех сил пытался найти какую-либо конкретную информацию о разработке производного типа. Я думаю, что лучший способ обсудить это через несколько вариантов. Я составил несколько участков кода с различными приложениями производного типа. Я бы предпочел использовать динамические массивы для nparts
, index
и refs
. Я пропустил разделы кода, которые на самом деле используют структуру (их нет, потому что я сам ее придумал), но показаны примеры, и в подпрограмме я намереваюсь использовать все значения в структуре хотя бы один раз.
Вариант А. Используйте статические массивы в производном типе. Недостатком является то, что мне пришлось бы угадывать размер массива во время компиляции.
! 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
Вариант Б. Использовать динамические массивы в производном типе.
! 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
требуется память packs
раз с assembly(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.
Вопросы:
- Какая версия является правильным/ожидаемым методом разработки производного типа для показанного примера цикла
do
? Какая версия наиболее оптимизирована, учитывая, что мне нужны возможности динамического массива? - Возможно, связано с вышеизложенным. Как распределяется память и как осуществляется доступ? Стоит ли использовать
SEQUENCE
? Я думаю, что выделенные массивы в любом случае не будут отображаться последовательно. Разве это не указывает на то, что вариант C является лучшим, поскольку каждый разделassembly
меньше? - Должен ли я разделить этот производный тип на несколько производных типов или вообще избавиться от него и просто придерживаться переменных? Я буду использовать этот производный тип в нескольких подпрограммах и помещу его в модуль.
kind=8
действительно уродлив, избегайте магических констант! Это не значит 8 байт! По крайней мере, не во всех компиляторах. - person Vladimir F   schedule 10.12.2016