Есть ли проблемы с использованием jagged-массивов в Фортране с несколькими уровнями распределения?

В своем коде на Фортране я хочу использовать зубчатые массивы с несколькими уровнями распределения. Пример кода того, что я имею в виду,

module nonsquare_matrix_mod
implicit none

   type :: nonsquare_matrix 
      integer :: d
      real*8, dimension(:), allocatable :: vector
   end type nonsquare_matrix

   type(nonsquare_matrix),dimension(:),allocatable :: mymatrix

end module nonsquare_matrix_mod

program nonsquare_matrix_test
   use nonsquare_matrix_mod
   implicit none

integer, parameter :: max_size=50
integer :: i

allocate(mymatrix(max_size))
do i=1,max_size
    allocate(mymatrix(i) % vector(i))
end do

print *, "allocated"


end program

Я хочу реализовать эту стратегию программирования, чтобы сохранить память. Я знаю, что память, сохраненная в этом примере, не слишком велика, но для моего реального проекта я работаю с гораздо большими структурами данных. Мне было интересно, есть ли какие-либо опасности с этой практикой программирования, например, данные не хранятся непрерывно или более подвержены утечкам памяти. Или это полезный способ экономии памяти без многих недостатков? Спасибо.


person user1910489    schedule 13.02.2013    source источник
comment
Выглядит хорошо для меня, и я использовал этот подход в прошлом. Сколько памяти вы сэкономите, будет зависеть от изменения длины массива между массивами. Лучше всего сначала написать код, который наиболее интуитивно понятен вам. Я бы не беспокоился об утечках памяти, пока вы держитесь подальше от указателей.   -  person milancurcic    schedule 13.02.2013


Ответы (1)


Поскольку вы используете только выделяемые массивы, у вас не будет утечки памяти, как это может быть при использовании указателей. Является ли зубчатый массив разумным решением вашей проблемы, во многом зависит от структуры ваших данных. Несколько моментов, которые следует отметить:

  • Ваш массив действительно не будет смежным. Это имеет несколько последствий, таких как худшее поведение кэширования при доступе к последующим строкам.

  • Вы должны выделить каждую строку через allocate отдельно. Если это происходит очень часто (например, внутри цикла), это может быть проблемой, поскольку выделение — довольно «медленная» операция.

  • Если строки в вашем массиве действительно сильно различаются по размеру (и у вас не слишком много строк), вы можете сэкономить значительный объем памяти.

Если длина строк задана во время их создания и не изменяется впоследствии (и вы хорошо догадываетесь, сколько максимально элементов у вас будет во всем массиве), вы можете выделить большой буферный массив, куда вы поместите в строках и массив индексов, который содержит позицию первого элемента этой строки в массиве буферов:

 program nonsquare_matrix_test
  implicit none

  integer, parameter :: dp = kind(1.0d0)
  integer, parameter :: maxlines = 50
  integer, parameter :: maxelements = 5000
  real(dp), allocatable :: buffer(:)
  integer, allocatable :: rowindex(:)
  integer :: ii

  allocate(buffer(maxelements))
  allocate(rowindex(maxlines + 1))
  rowindex(1) = 1
  do ii = 1, maxlines
    rowindex(ii + 1)  = rowindex(ii) + ii
  end do
  ! ...  
  ! Omitting the part which fills up the array
  ! ...
  ! Accessing a given line (e.g. line 5)
  print *, "Content of line 5:"
  print *, buffer(rowindex(5):rowindex(6)-1)

end program nonsquare_matrix_test
person Bálint Aradi    schedule 13.02.2013