Optimization Fortran:有效的矩阵向量乘法
我有一段代码是一个重要的瓶颈:Optimization Fortran:有效的矩阵向量乘法,optimization,fortran,matrix-multiplication,blas,Optimization,Fortran,Matrix Multiplication,Blas,我有一段代码是一个重要的瓶颈: do s = 1,ns msum = 0.d0 do k = 1,ns msum = msum + tm(k,s)*f(:,:,k) end do m(:,:,s) = msum end do 这是每个x,y的简单矩阵向量积m=tm*f(其中f是长度k) 我考虑过使用BLAS例程,但我不确定是否有允许沿特定维度进行乘法的例程(k)。你们有什么好的建议吗?不幸的
do s = 1,ns
msum = 0.d0
do k = 1,ns
msum = msum + tm(k,s)*f(:,:,k)
end do
m(:,:,s) = msum
end do
这是每个x,y
的简单矩阵向量积m=tm*f
(其中f
是长度k
)
我考虑过使用BLAS例程,但我不确定是否有允许沿特定维度进行乘法的例程(
k
)。你们有什么好的建议吗?不幸的是,你们没有提到f
的实际形状,即x
和y
的数量。由于您提到这段代码是一个瓶颈,因此您可以而且应该替换msum
,并使用内存m(:,:,s)
,并节省循环中的第一步,例如
do s = 1,ns
m = tm(k,1)*f(:,:,k)
do k = 2, ns
m(:,:,s) = m(:,:,s) + tm(k,s)*f(:,:,k)
end do
end do
第二,更一般的方法通过存储在
tm(:,1:ns)
中的标量因子,存在ns
和nK
2D矩阵f(:,:,1:nK)
。目标是将这些总和存储在m(:,:,1:ns)
中。为什么不将元素wrtx
和y
相加,利用结果利用相邻的内存段呢?您已经提到,您可以重新设计k
是f
中的第一个维度,即f(k,:,:)
。
仅考虑期望的结果,您应该拥有相互独立的
ns
2D矩阵m(:,:,1:ns)
(外部循环保持不变)。让我们暂时放下这个维度。问题就变成了:
m(:,:)=\sum{k=1}^{ns}tm_k*f_k(:,:)
因此,我们应该对k
求和,例如,用f(k,:,:)
来确定m(:,:)
,如下所示(注意,我再次为s
添加了外循环):
有关其用法的详细信息,请参阅的文档
当然,上述排除循环的第一步以通过零来避免初始化的建议也可以很好地应用。你能重新设计
f
,使k
成为第一维度吗?是的,我能,这相对容易,但是数据在内存中是不连续的,非常有趣!我会实施,看看是否有任何改进。既然你问了,x,y的大小取决于域的大小,但现在假设它们固定在100。k的大小固定为9。@nLoije关于x和y的大小:取决于通过BLAS的实际速度(或者更确切地说,使用OpenBLAS,速度更快!),重新排列维度可能会或可能不会提高算法的整体速度。然而,这是特定于您的问题和代码的,应该值得测试。
nK = size(f, 1) ! the "k"s
nX = size(f, 2) ! the "x"s
nY = size(f, 3) ! the "y"s
m = 0.d0
do s = 1, ns
do ii = 1, nY
call DGEMV('N', nK, nY, &
1.d0, f(:,:,nY), 1, tm(:,s), 1, &
1.d0, m(:,nY,s), 1)
end do !ii
end do !s