Fortran:稀疏数组或列表

Posted

技术标签:

【中文标题】Fortran:稀疏数组或列表【英文标题】:Fortran: sparse arrays or lists 【发布时间】:2012-02-09 14:35:23 【问题描述】:

Fortran 中是否有任何稀疏数组或等效列表的实现。

在计算大型数据集的阶段,我们将一个大小为n=10000 的数组传递给子程序以对其进行处理。例如,在其中找到相似的元素并为每个项目按顺序列出它们。即对于item one,通过列表(数组)查找所有相似的item,并存储结果标记。结果可能像每个元素的列表一样大。请注意,关于标准,我们使用的相似性不是对称的,这意味着我们需要完全迭代所有项目的评估。因此,根据所使用的标准,每个结果的长度可能不同。因此,存储所有结果需要稀疏数组/列表,这在 Python 中可用:

R = an array # an array L = [] # list initialization for e in R: # iteration on all elements of R r = similars(e,R,criteria) # r is array & different in size for each element L.append(r) # store the ranks in list L

为了简单起见,现在我们使用 Fortran 中的常用数组,其中 n<=1000n*n。如您所见,对于较大的尺寸,这是一个非常低效的想法。 有什么解决办法吗?

【问题讨论】:

linked list 在这里可能有用。 @Anycorn F90。和 GCC4.5 @Chris 感谢您的链接。看起来很有希望。 Fortran 链表最近出现在 Stack Overflow 上 ***.com/questions/8648779/… 【参考方案1】:

没有链表的解决方案。

这里假设向量“r”包含双精度值。

请注意,此解决方案不使用指针,只使用可分配数组,这样可以保证避免内存泄漏。重新分配的数量是有限的(log2(list%n)),但是可以接受分配 list%result 的大小大于实际需要的大小(最多两次)。

最后,向量“r”在列表中重复了(在python版本中不是这种情况)。

module extendable_list

implicit none

type result_type
  double precision,allocatable :: vector(:)
end type

type list_type
  integer :: n
  type(result_type),allocatable :: result(:)
end type

contains

subroutine append(list,r)
  type(list_type),intent(inout) :: list
  double precision,intent(in)   :: r(:)
  type(result_type),allocatable :: temporary(:)
  integer :: i
  if(.not.allocated(list%result)) then
    allocate(list%result(10))
    list%n=0
  else if(list%n >= size(list%result)) then
    allocate(temporary(2*list%n))
    do i=1,list%n
      call move_alloc(list%result(i)%vector,temporary(i)%vector)
    enddo
    call move_alloc(temporary,list%result)
  endif
  list%n=list%n+1
  allocate(list%result(list%n)%vector(size(r)))
  list%result(list%n)%vector=r
end subroutine

end module

program main
  use extendable_list
  implicit none
  type(list_type) :: list
  integer :: i
  do i=1,10
    call append(list,(/1.d0,3.d0/))
    call append(list,(/7.d0,-9.d0,45.d0/))
  enddo
  do i=1,list%n
    write(*,*) list%result(i)%vector
  enddo
end program

结果:

coul@b10p5001:~/test$ ifort t65.f90
coul@b10p5001:~/test$ ./a.out
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     
   1.00000000000000        3.00000000000000     
   7.00000000000000       -9.00000000000000        45.0000000000000     

【讨论】:

谢谢,这真的很有帮助。是否有可能将任意类型作为 result_type?我喜欢将 REAL*8 存储为第一个列表项,接下来是 COMPLEX*16,DIMENSION(:,:) 等等...【参考方案2】:

您可能有兴趣通过 ISO-C-Binding 使用 Judy-Arrays。它为您提供动态稀疏数组的功能。否则,如果您需要,我会推荐 Francois Jacq 解决方案,可能会添加额外的排序条目列表,以对给定值执行二进制搜索。 根据我的经验,这两种方法都非常有效。

【讨论】:

以上是关于Fortran:稀疏数组或列表的主要内容,如果未能解决你的问题,请参考以下文章

交错稀疏排序数组

如何将 numpy.matrix 或数组转换为 scipy 稀疏矩阵

数据结构与算法之java语言实现:稀疏数组

R中的多维稀疏数组(3路张量)

稀疏矩阵的运算

稀疏数组