Fortran 中的稀疏存储:仅读和写

Sparse Storage in Fortran: Only Reading and Writing

我有一个多维数组(目标是允许大约 100 个),每个维的大小约为 2^10,我只需要在其中存储大约 1000 个双精度系数。除了读写之外,我不需要对这个数组做任何操作。代码是用 Fortran 90 编写的。

我假设如果我的库像 this answer 中提到的库之一,我将能够存储它,但这会针对简单的读写操作进行优化吗?有没有一个图书馆可以最有效地达到这个目的?

编辑:通过“简单的读写操作”我的意思如下。假设

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 所需的内存不应随着维数的增加而爆炸。

嗯,我仍然不完全清楚你的数据的性质和你想要使用它的方式。

如果你需要的是索引数据,索引不连续, 稀疏矩阵可能是一个答案,并且已经在 Internet 上实现了许多解决方案(如您提供的 link 所示)。但对于我认为你正在尝试做的事情来说,这可能会有点矫枉过正。也许一个简单的数据类型可以满足您的目的,如下所示:

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 值和索引索引,并按位置关联它们.