朱莉娅:BLAS.gemm!() 参数

Julia : BLAS.gemm!() parameters

我想使用 BLAS 包。为此,gemm() 函数的前两个参数的含义对我来说并不明显。 参数'N''T'代表什么?

 BLAS.gemm!('N', 'T', lr,  alpha, A, B, beta, C)

BLAS.gemmBLAS.gemm! 和有什么不一样?

根据 documentation

gemm!(tA, tB, alpha, A, B, beta, C)

Update C as alpha * A * B + beta*C or the other three variants according to tA (transpose A) and tB. Returns the updated C.

注意:这里的alphabeta必须是float类型的标量。 ABC 都是矩阵。由您来确保矩阵维度匹配。

因此,tAtB 参数指的是在相乘之前是否要对 AB 应用转置运算。请注意,这将花费您一些计算时间和分配 - 转置不是免费的。 (因此,如果你打算多次应用乘法,每次都使用相同的转置规范,你最好从一开始就将矩阵存储为转置版本)。 Select N 不转置,T 转置。你必须select其中之一。

gemm!()gemv!() 的区别在于,对于gemm!(),您已经需要分配矩阵C! 是一个 "modify in place" 信号。考虑以下对它们不同用途的说明:

A = rand(5,5)
B = rand(5,5)
C = Array(Float64, 5, 5)

BLAS.gemm!('N', 'T', 1.0, A, B, 0.0, C)
D = BLAS.gemm('N', 'T', 1.0, A, B)

julia> C == D
true

本质上,其中每一个都执行 C = A * B' 的计算。 (从技术上讲,gemm!() 执行 C = (0.0)*C + (1.0)*A * B'。)

因此,就地修改的语法 gemm!() 在某些方面有点不寻常(除非您已经使用过像 C 这样的语言,在这种情况下它看起来非常直观)。在像 Julia 这样的高级面向对象语言中调用函数赋值时,您没有经常使用的显式 = 符号。

如上图所示,gemm!()gemm() 在这种情况下的结果是相同的,尽管实现该结果的语法和过程略有不同。然而,实际上,两者之间的性能差异可能很大,具体取决于您的用例。特别是,如果您要多次执行该乘法运算,每次 replacing/updating C 的值,那么 gemm!() 可能会快一点,因为您不需要每次都重新分配新内存,这确实有时间成本,无论是在初始内存分配中还是在以后的垃圾收集中。