我有一个构建稀疏矩阵的子例程,我需要调用它几次。然而,似乎如果我多次调用这个子例程(和/或如果稀疏矩阵非常大),我的机器中的内存消耗就会开始累积。鉴于我的矩阵非常大,重复调用子例程最终会使程序崩溃。看起来 Fortran 在完成每个子例程调用后并没有刷新/释放分配的内存。
我正在使用 oneAPI MKL 附带的 Sparse BLAS 库并使用
ifort
编译器构建这些稀疏矩阵。
下面,我有一个例子,我使用 Sparse BLAS 多次构建了一个小矩阵。迭代不会改变任何东西,但据我了解,内存消耗不应在每次迭代后开始增加。然而,确实如此。如果我在此循环中使用常规(密集)矩阵而不是使用稀疏 BLAS,则内存消耗根本不会增加。例如,如果我注释循环中调用
mkl_sparse_d_create_csr
的最后一行,则程序不会崩溃。
program test
use iso_c_binding
use mkl_spblas
implicit none
integer,parameter :: n = 5
integer :: iter,i,j,stat
real :: csr_ref(n,n)
integer :: count_row,count_nnz
integer :: jcol(1),irow(n+1)
real(C_DOUBLE) :: vals(1)
type(SPARSE_MATRIX_T) :: csr
! Dummy matrix
csr_ref = 0.0
csr_ref(1,1) = 1.0
! Iterating many times
do iter = 1,1000000000
! Builing CSR matrix
irow = 1
count_nnz = 0
do i = 1,n
count_row = 0
do j = 1,n
if (abs(csr_ref(i,j)) > 1e-4) then
count_row = count_row + 1
count_nnz = count_nnz + 1
vals(count_nnz) = csr_ref(i,j)
jcol(count_nnz) = j
end if
end do
irow(1+i) = count_row + irow(i)
end do
! Create sparse matrix
stat = mkl_sparse_d_create_csr(csr, SPARSE_INDEX_BASE_ONE, n, n, irow(1:n), irow(2:n+1), jcol, vals)
end do
end program test
这里有什么问题?
问题是你需要调用
mkl_sparse_destroy
来恢复mkl_sparse_?_create_csr
分配的内存。这在 mkl_sparse_destroy
的在线文档中有明确说明,但不幸的是,在 mkl_sparse_?_create_csr
的在线文档中没有明确说明。
参考资料:
mkl_sparse_?_create_csr
的英特尔 MKL 文档:https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-fortran/2024-0/mkl-sparse-create-csr.html
mkl_sparse_destroy
的英特尔 MKL 文档:https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-fortran/2024-0/mkl-sparse-destroy.html