Разреженное хранилище в Фортране: только чтение и запись - PullRequest
0 голосов
/ 24 мая 2018

У меня есть массив с несколькими измерениями (цель состоит в том, чтобы учесть около 100), и каждое измерение имеет размер около 2 ^ 10, и мне нужно только сохранить в нем около 1000 коэффициентов двойной точности.Мне не нужно делать никаких операций с этим массивом, кроме чтения и записи в него.Код написан на Фортране 90.

Я предполагаю, что если я буду использовать библиотеку, подобную одной из упомянутых в этот ответ , я смогу сохранить это, но будет ли этооптимизирован для простых операций чтения и записи?Есть ли библиотека, которая была бы наиболее эффективной для этой цели?

Редактировать: Под " простыми операциями чтения и записи " я имею в виду следующее.Предположим, что

REAL(8), DIMENSION(1000)   :: coeff1
INTEGER, DIMENSION(1000,5) :: index

Я хочу определить coeff2 для хранения значений в coeff1, а затем прочитать его по индексам в index, то есть

DO i = 1,1000
     index(i,:) = [something]
     coeff1(i)  = [another something]
     coeff2(index(i,1),index(i,2),index(i,3),index(i,4),index(i,5)) = coeff1(i)
ENDDO

Тогда длялюбой i Я хотел бы получить доступ к значению

coeff2(index(i,1),index(i,2),index(i,3),index(i,4),index(i,5))

как можно быстрее.Быть способным сделать это быстро - это то, что я имею в виду под " эффективными ".

Поскольку индексы в [something] не превышают 2 ^ 10, в настоящее время я определяю coeff2 следующим образом:

REAL(8), DIMENSION(2**10,2**10,2**10,2**10,2**10) :: coeff2

, но это слишком расточительно для памяти, особенно потому, что мне нужно увеличить количество измерений, теперь 5, до порядка 100, и большинство элементов этого массива равны 0. Итак, еще одна мерадля меня важна эффективность в том, что память, необходимая для хранения coeff2, не должна взорваться при увеличении количества измерений.

1 Ответ

0 голосов
/ 24 мая 2018

Что ж, мне до сих пор не до конца ясна природа ваших данных и то, как вы хотите их использовать.

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

program indexed_values
  implicit none

  type :: indexed
    integer :: index
    real(8) :: value
  end type

  integer, parameter :: n_coeffs = 1000
  integer, parameter :: n_indices = 5
  integer :: i

  real(8), dimension(n_coeffs) :: coeff1
  integer, dimension(n_coeffs, n_indices) :: index
  type(indexed), dimension(n_coeffs, n_indices) :: coeff2
  type(indexed) :: var

  do i = 1, n_coeffs
    index(i, :) = [1, 2, 4, 16, 32] * i ! your calc here
    coeff1(i) = real(i * 3, 8) ! more calc here
    coeff2(i, :)%index = index(i, :)
    coeff2(i, :)%value = coeff1(i)
  end do

  ! that's how you fetch the indices and values by stored position
  var = coeff2(500, 2)
  print*, var%index, var%value ! outputs: 1000   1500.0

  ! that's how you fetch a value by its index
  print*, fetch_by_index(coeff2(500, :), 1000) ! outputs: 1500.0

contains

  real(8) function fetch_by_index(indexed_pairs, index)
    type(indexed), dimension(:) :: indexed_pairs
    integer, intent(in) :: index
    integer :: i

    do i=1, size(indexed_pairs)
      if(index == indexed_pairs(i)%index) then
        fetch_by_index = indexed_pairs(i)%value
        return
      end if
    end do
    stop "No value stored for this index"
  end
end

Предоставленная функция для извлечения значений по ее индексам могла бы быть улучшена, если ваши индексы всегда будут храниться в порядке возрастания (нет необходимости проходить через всесписок провалиться).Более того, если вы предоставите постоянный результат coeff1 для всех индексов в каждой строке, вы могли бы сделать это еще лучше и совсем не иметь массива coeff2, просто иметь coeff1 для значений и индекс для индексов и сопоставить их по положению.

...