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 值和索引索引,并按位置关联它们.
我有一个多维数组(目标是允许大约 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 值和索引索引,并按位置关联它们.