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

时间:2018-05-24 15:59:51

标签: fortran sparse-matrix fortran90

我有一个具有多个维度的数组(目标是允许大约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所需的内存不会爆炸。

1 个答案:

答案 0 :(得分:2)

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

如果您需要的是索引数据,其索引不连续, 稀疏矩阵可以作为答案,并且已经在互联网上实现了许多解决方案(如您提供的链接所示)。但也许这对我认为你想做的事情来说太过分了。也许一个简单的数据类型可以满足您的目的,例如:

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,并按位置关联它们