简体   繁体   English

将块对角矩阵乘以向量的有效方法

[英]efficient way of multiplying block diagonal matrix by vector

I have a matrix C structured as following:我有一个矩阵 C 结构如下: C

Need to multiply its transpose by vector x .需要将其转置乘以向量x

with the upper part its clear - take slices of the first half of the vector say:上半部分清晰 - 取矢量前半部分的切片说:

suppose indexation starts at 1.假设索引从 1 开始。

x1 = x(1:(n-1)*(m-1))

x2 = -x(m:n*(m-1))

then increment partially:然后部分增加:

x(1:(n-1)*(m-1)) += x1

x(m:n*(m-1))+=x2

but how to deal with the lower (left after transpose) part?但是如何处理下部(转置后的左侧)部分? any suggestions?有什么建议么?

You can't do it with whole-array operations, so you will need a loop.你不能用整个数组操作来做到这一点,所以你需要一个循环。

integer :: m,n
integer :: x((m-1)*(n-1))
integer :: y((m-1)*n+m*(n-1))

integer :: offset, block
integer :: xstart, ystart

offset = n*(m-1)
block = m-1

y = 0
y(:n*block) = y(:n*block) + x
y(m:(n+1)*block) = y(m:(n+1)*block) - x
do i=1,n-1
  xstart = (m-1)*(i-1)+1
  ystart = offset+m*(i-1)+1
  y(ystart  :ystart+block  ) = y(ystart  :ystart+block  ) - x(xstart:xstart+block)
  y(ystart+1:ystart+block+1) = y(ystart+1:ystart+block+1) + x(xstart:xstart+block)
enddo

It's never a good idea to store zeros in a matrix.在矩阵中存储零绝不是一个好主意。 If you do, it means that the data structure you're using is sub-optimal for the problem you're trying to solve.如果这样做,则意味着您使用的数据结构对于您要解决的问题不是最佳的。

Since your non-square matrix structure is made of diagonal or banded blocks, it seems like most of it elements will always be zero.由于您的非方阵结构由对角线或带状块组成,因此大多数元素似乎始终为零。 I suggest you store your matrix using a sparse format like Compressed Sparse Row (CSR) (see for example Sparse Matrix vector product in Fortran ).我建议您使用压缩稀疏行 (CSR) 之类的稀疏格式存储矩阵(例如,参见Fortran 中的稀疏矩阵向量积)。 With that example, a transposed matrix-vector product would look pretty simply在这个例子中,转置矩阵向量乘积看起来很简单


function transposed_matvec(A,x) result(b)
   type(CSRMatrix), intent(in) :: A
   real(real64), intent(in) :: x(:) 
   real(real64) :: b(A%n),aij
   integer :: j1,j2,row,col

   if (size(x)/=A%m) stop ' transposed_matvec: invalid array size '

   ! Initialize b
   b = 0.0_real64  
 
   ! Compute product by rows because data is row-ordered
   do row=1,A%m
     j1 = A%rowPtr(row)
     j2 = A%rowPtr(row+1)-1; 

     do j=j1,j2
        col = A%colPtr(j)
        aij = A%aij(j)
        b(col) = MxV(col) + aij*x(col) 
     end do
   end do   

end function transposed_matvec

If you used compressed sparse column storage (CSC) instead, the matrix would be stored by columns already, so the transposed matvec routine would look identical to the direct matvec routine for CSR at the example in the link.如果您改用压缩稀疏列存储 (CSC),则矩阵将已经按列存储,因此转置的 matvec 例程看起来与链接中示例中用于 CSR 的直接 matvec 例程相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM