`sgemm` 的维度参数是如何工作的?
How does the dimention argument of `sgemm` work?
我正在尝试理解 sgemm
的文档,因为我正在将代码从使用此库转换到其他库。
函数原型为
sgemm ( character TRANSA,
character TRANSB,
integer M,
integer N,
integer K,
real ALPHA,
real, dimension(lda,*) A,
integer LDA,
real, dimension(ldb,*) B,
integer LDB,
real BETA,
real, dimension(ldc,*) C,
integer LDC
)
我无法理解 LDA
和 LDB
的角色。文档说
LDA is INTEGER
On entry, LDA specifies the first dimension of A as declared
in the calling (sub) program. When TRANSA = 'N' or 'n' then
LDA must be at least max( 1, m ), otherwise LDA must be at
least max( 1, k ).
指定A的第一个维度是什么意思?这像是在行和列专业之间切换吗?或者这是切片张量?
LD代表主尺寸。 BLAS 最初是 Fortran 77 子程序库,在 Fortran 中矩阵按列存储:A(i,j)
在内存中紧跟 A(i+1,j)
,与 C/C++ 相反,其中 a[i][j]
后跟 a[i][j+1]
。为了访问维度为 A(LDA,*)
(读取为 LDA
行和未指定数量的列)的矩阵的元素 A(i,j)
,您需要从中查找 (j-1)*LDA + (i-1)
元素矩阵的开头(Fortran 数组默认为 1 索引),因此您需要知道 LDA
的值。您不需要知道实际的列数,因此不需要知道虚拟参数中的 *
。
在C/C++中也是一样。如果你有一个声明为 a[something][LDA]
的二维数组,那么元素 a[i][j]
位于数组开始后的 i*LDA + j
个位置,你只需要知道 LDA
- 值something
的地址不影响a[i][j]
.
的地址计算
尽管 GEMM 在 M x K
矩阵 A
上运行,但实际数据可能嵌入到更大的矩阵 LDA x L
中,其中 LDA >= M
和 L >= K
,因此明确指定了 LDA
。这同样适用于 LDB
和 LDC
.
BLAS 是多年前开发的,当时计算机编程与今天大不相同。特别是内存管理,不像现在这样灵活。分配一个大矩阵,然后使用和重用它的一部分来存储较小的矩阵是一种常态。此外,GEMM 广泛用于,例如,在各种子矩阵上工作的迭代算法,将数据保留在原始矩阵中并仅指定子矩阵的位置和维度会更快,因此您需要提供两个维度。
从 Fortran 90 开始,该语言具有数组切片和自动数组描述符,允许发现切片的维度和更大矩阵的维度,因此如果 GEMM 是用 Fortran 90 或更高版本编写的,它不会' 就其论点而言如此冗长。但即使是这种情况,C 也没有数组描述符,因此您仍然必须提供所有这些参数才能使 GEMM 可从 C 调用。在 C++ 中,可以将描述符隐藏在矩阵中 class,许多数学库实际上也是这样做的(例如,Scythe)。
我正在尝试理解 sgemm
的文档,因为我正在将代码从使用此库转换到其他库。
函数原型为
sgemm ( character TRANSA,
character TRANSB,
integer M,
integer N,
integer K,
real ALPHA,
real, dimension(lda,*) A,
integer LDA,
real, dimension(ldb,*) B,
integer LDB,
real BETA,
real, dimension(ldc,*) C,
integer LDC
)
我无法理解 LDA
和 LDB
的角色。文档说
LDA is INTEGER
On entry, LDA specifies the first dimension of A as declared in the calling (sub) program. When TRANSA = 'N' or 'n' then LDA must be at least max( 1, m ), otherwise LDA must be at least max( 1, k ).
指定A的第一个维度是什么意思?这像是在行和列专业之间切换吗?或者这是切片张量?
LD代表主尺寸。 BLAS 最初是 Fortran 77 子程序库,在 Fortran 中矩阵按列存储:A(i,j)
在内存中紧跟 A(i+1,j)
,与 C/C++ 相反,其中 a[i][j]
后跟 a[i][j+1]
。为了访问维度为 A(LDA,*)
(读取为 LDA
行和未指定数量的列)的矩阵的元素 A(i,j)
,您需要从中查找 (j-1)*LDA + (i-1)
元素矩阵的开头(Fortran 数组默认为 1 索引),因此您需要知道 LDA
的值。您不需要知道实际的列数,因此不需要知道虚拟参数中的 *
。
在C/C++中也是一样。如果你有一个声明为 a[something][LDA]
的二维数组,那么元素 a[i][j]
位于数组开始后的 i*LDA + j
个位置,你只需要知道 LDA
- 值something
的地址不影响a[i][j]
.
尽管 GEMM 在 M x K
矩阵 A
上运行,但实际数据可能嵌入到更大的矩阵 LDA x L
中,其中 LDA >= M
和 L >= K
,因此明确指定了 LDA
。这同样适用于 LDB
和 LDC
.
BLAS 是多年前开发的,当时计算机编程与今天大不相同。特别是内存管理,不像现在这样灵活。分配一个大矩阵,然后使用和重用它的一部分来存储较小的矩阵是一种常态。此外,GEMM 广泛用于,例如,在各种子矩阵上工作的迭代算法,将数据保留在原始矩阵中并仅指定子矩阵的位置和维度会更快,因此您需要提供两个维度。
从 Fortran 90 开始,该语言具有数组切片和自动数组描述符,允许发现切片的维度和更大矩阵的维度,因此如果 GEMM 是用 Fortran 90 或更高版本编写的,它不会' 就其论点而言如此冗长。但即使是这种情况,C 也没有数组描述符,因此您仍然必须提供所有这些参数才能使 GEMM 可从 C 调用。在 C++ 中,可以将描述符隐藏在矩阵中 class,许多数学库实际上也是这样做的(例如,Scythe)。