使用 MKL 的矢量稀疏矩阵乘法
Vector- Sparce Matrix multiplication using MKL
我有简单的 Fortran 代码,可将 A=[1,1;1,1] 矩阵转换为 CSR 稀疏格式,然后将其乘以 x=(100,200) 作为向量,y=A*x。
不幸的是,结果是奇怪的 y=(200,200) 而它应该是 y =(300,300) 向量。谢谢
program main
implicit none
include 'mkl_spblas.fi'
integer :: nzmax, nnz, job( 8 ), m, n, lda, info, irow, k
double precision :: A(2,2)
double precision, allocatable :: Asparse(:)
integer, allocatable :: ia(:), ja(:)
double precision:: x(2)
double precision:: y(2)
A(1,1) = 1.d0
A(1,2) = 1.d0
A(2,1) = 1.d0
A(2,2) = 1.d0
x(1) = 100.d0
x(2) = 200.d0
!! Give an estimate of the number of non-zeros.
nzmax = 4
print *, "nzmax = ", nzmax
m = size( A, 1 ) !! number of rows
n = size( A, 2 ) !! number of columns
lda = m !! leading dimension of A
allocate( Asparse( nzmax ) )
allocate( ja( nzmax ) ) !! <-> columns(:)
allocate( ia( m + 1 ) ) !! <-> rowIndex(:)
job( 1 ) = 0 !! convert dense to sparse A
job( 2:3 ) = 1 !! use 1-based indices
job( 4 ) = 2 !! use the whole A as input
job( 5 ) = nzmax !! maximum allowed number of non-zeros
job( 6 ) = 1 !! generate Asparse, ia, and ja as output
call mkl_ddnscsr( job, m, n, A, lda, Asparse, ja, ia, info )
if ( info /= 0 ) then
print *, "insufficient nzmax (stopped at ", info, "row)"; stop
endif
nnz = ia(m+1)
print *, "number of non-zero elements = ", nnz
do irow = 1, m
!! This loop runs only for rows having nonzero elements.
do k = ia( irow ), ia( irow + 1 ) - 1
print "(2i5, f15.8)", irow, ja( k ), Asparse( k )
enddo
enddo
call mkl_cspblas_dcsrgemv('n', m, Asparse, ia, ja, x, y)
print*, y
end program
那是因为您正在使用 c-style 索引来调用 MKL 子例程。
mkl_cspblas_dcsrgemv 是 zero-based 索引。
对于您的程序,您应该使用 mkl_dcsrgemv,即 one-based 索引。
我有简单的 Fortran 代码,可将 A=[1,1;1,1] 矩阵转换为 CSR 稀疏格式,然后将其乘以 x=(100,200) 作为向量,y=A*x。 不幸的是,结果是奇怪的 y=(200,200) 而它应该是 y =(300,300) 向量。谢谢
program main
implicit none
include 'mkl_spblas.fi'
integer :: nzmax, nnz, job( 8 ), m, n, lda, info, irow, k
double precision :: A(2,2)
double precision, allocatable :: Asparse(:)
integer, allocatable :: ia(:), ja(:)
double precision:: x(2)
double precision:: y(2)
A(1,1) = 1.d0
A(1,2) = 1.d0
A(2,1) = 1.d0
A(2,2) = 1.d0
x(1) = 100.d0
x(2) = 200.d0
!! Give an estimate of the number of non-zeros.
nzmax = 4
print *, "nzmax = ", nzmax
m = size( A, 1 ) !! number of rows
n = size( A, 2 ) !! number of columns
lda = m !! leading dimension of A
allocate( Asparse( nzmax ) )
allocate( ja( nzmax ) ) !! <-> columns(:)
allocate( ia( m + 1 ) ) !! <-> rowIndex(:)
job( 1 ) = 0 !! convert dense to sparse A
job( 2:3 ) = 1 !! use 1-based indices
job( 4 ) = 2 !! use the whole A as input
job( 5 ) = nzmax !! maximum allowed number of non-zeros
job( 6 ) = 1 !! generate Asparse, ia, and ja as output
call mkl_ddnscsr( job, m, n, A, lda, Asparse, ja, ia, info )
if ( info /= 0 ) then
print *, "insufficient nzmax (stopped at ", info, "row)"; stop
endif
nnz = ia(m+1)
print *, "number of non-zero elements = ", nnz
do irow = 1, m
!! This loop runs only for rows having nonzero elements.
do k = ia( irow ), ia( irow + 1 ) - 1
print "(2i5, f15.8)", irow, ja( k ), Asparse( k )
enddo
enddo
call mkl_cspblas_dcsrgemv('n', m, Asparse, ia, ja, x, y)
print*, y
end program
那是因为您正在使用 c-style 索引来调用 MKL 子例程。
mkl_cspblas_dcsrgemv 是 zero-based 索引。 对于您的程序,您应该使用 mkl_dcsrgemv,即 one-based 索引。