【发布时间】:2012-12-01 21:54:54
【问题描述】:
在编程密集矩阵计算时,是否有任何理由选择行优先布局而不是列优先布局?
我知道,根据所选矩阵的布局,我们需要编写适当的代码以有效地使用高速缓存来提高速度。
以行为主的布局似乎更自然、更简单(至少对我而言)。但是像 LAPACK 这样用 Fortran 编写的主要库都使用列主布局,所以做出这个选择肯定是有原因的。
【问题讨论】:
标签: performance matrix fortran
在编程密集矩阵计算时,是否有任何理由选择行优先布局而不是列优先布局?
我知道,根据所选矩阵的布局,我们需要编写适当的代码以有效地使用高速缓存来提高速度。
以行为主的布局似乎更自然、更简单(至少对我而言)。但是像 LAPACK 这样用 Fortran 编写的主要库都使用列主布局,所以做出这个选择肯定是有原因的。
【问题讨论】:
标签: performance matrix fortran
FORTRAN 旨在解决科学和工程问题。从科学的角度来看,以列为主的存储更为自然,因为一般的线性代数约定使用列向量并且通常将矩阵视为列向量的串联。在矩阵向量乘法中,列向量位于右侧(乘法后),连续矩阵在左侧进一步添加,例如B*(A*x)。 COBOL、PL/1 和 C 等语言将矩阵视为行记录的集合,因此对它们而言,行优先顺序更自然。
在线性代数中,向量由其坐标表示:x = x[1]*e1 + x[2]*e2 + ... + x[n]*en 其中x[i] 是向量坐标,ei 是i-th 基向量。在矩阵表示中,基向量是列向量。线性运算符A 然后作用于x,给出:
y = A*x = A*{x[1]*e1 + x[2]*e2 + ... x[n]*en}
= x[1]*(A*e1) + x[2]*(A*e2) + ... x[n]*(A*en)
在矩阵表示中,线性运算符A 由n 列组成,其中i 列是A 作用于i-th 基向量的结果,而A*x 则简单A 的列与 x 坐标的系数的线性组合。在 FORTRAN 中,这将是:
! Zero out the result vector
DO k = 1,n
y(k) = 0.0
END DO
! Iterate over the columns of A
DO i = 1,n
! Add the i-th column to the linear combination with a weight of x(i)
w = x(i)
DO k = 1,n
y(k) = y(k) + w*A(k,i)
END DO
END DO
这会自动优先使用 A 的列主要存储。这可能看起来很尴尬,但早在 50 年代,当 FORTRAN 诞生时,FMAC 硬件和寄存器优化并没有像现在这样流行。
【讨论】:
A*x 视为A 的列的线性组合。我将A*x 视为x 和A 的rows 的点积向量。在您的示例中切换到先迭代k,然后再迭代i,您将获得一个支持A 的行主要存储的版本。
我看不出有什么不同。两者都是将多维矩阵转换为线性内存顺序的好方法。转换方程非常相似。
还有 / 和 \ 。以及大端和小端。有人做出了选择,后来有人做出了另一个选择。
【讨论】: