我有一段代码是一个重要的瓶颈:
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
)进行乘法运算。你们有什么好建议吗?
答案 0 :(得分:3)
很遗憾,您没有提到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
其次,更普遍的appraoch
通过存储在ns
中的标量因子,nK
2D矩阵f(:,:,1:nK)
有tm(:,1:ns)
个总结。目标是将这些总和存储在m(:,:,1:ns)
中。为什么不总结元素方式wrt x
和y
来通过结果来利用contiguuos内存部分?您已经提到可以重新设计,k
是f
中的第一个维度,即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的文档。
当然,上述通过零来排除循环的第一步以避免初始化的建议也可以应用。