Fortran:有效的矩阵向量乘法

时间:2014-08-29 21:08:15

标签: 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

对于每个m=tm*f,这是一个简单的矩阵向量积f(其中k的长度为x,y)。

我考虑过使用BLAS例程,但我不确定是否允许沿特定维度(k)进行乘法运算。你们有什么好建议吗?

1 个答案:

答案 0 :(得分:3)

很遗憾,您没有提到f的实际形状,即xy的数量。既然你提到这段代码是一个瓶颈,你可以而且应该替换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

其次,更普遍的appraoch
通过存储在ns中的标量因子,nK 2D矩阵f(:,:,1:nK)tm(:,1:ns)个总结。目标是将这些总和存储在m(:,:,1:ns)中。为什么不总结元素方式wrt xy来通过结果来利用contiguuos内存部分?您已经提到可以重新设计,kf中的第一个维度,即f(k,:,:)
只考虑期望的结果,你应该有ns个二维矩阵m(:,:,1:ns)彼此独立(外环保持不变)。让我们暂时放下这个维度。然后问题变成:

  

m(:,:) = \ sum_ {k = 1} ^ {ns} tm_k * f_k(:,:)

因此,我们应该总结k,例如让f(k,:,:)确定m(:,:)如下(注意我再次为s添加外部循环):

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

有关其用法的更多详细信息,请参阅DGEMV的文档。

当然,上述通过零来排除循环的第一步以避免初始化的建议也可以应用。