我想使用BLAS包。为此,gemm()
函数的两个第一个参数的含义对我来说并不明显。
参数'N'
和'T'
代表什么?
BLAS.gemm!('N', 'T', lr, alpha, A, B, beta, C)
BLAS.gemm
和BLAS.gemm!
之间有什么区别?
答案 0 :(得分:3)
gemm!(tA,tB,alpha,A,B,beta,C)
根据tA(转置A)和tB将C更新为alpha * A * B + beta * C或其他三种变体。返回更新的C。
注意:此处,alpha
和beta
必须是float
类型标量。 A
,B
和C
都是矩阵。您可以确保矩阵尺寸匹配。
因此,tA
和tB
参数指的是您是否要在乘法之前将转置操作应用于A
或B
。请注意,这将花费您一些计算时间和分配 - 转置不是免费的。 (因此,如果您要多次应用乘法,每次使用相同的转置规范,最好将矩阵作为转置版本从头开始存储)。选择N
表示无转置,T
进行转置。您必须选择其中一个。
gemm!()
和gemv!()
之间的区别在于gemm!()
您已经需要分配矩阵C
。 !
是“就地修改”信号。请考虑以下不同用途的说明:
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()
的结果是相同的,即使实现该结果的语法和过程略有不同。但实际上,根据您的使用情况,两者之间的性能差异可能很大。特别是,如果您要多次执行乘法运算,每次替换/更新C
的值,那么gemm!()
可能会更快一点,因为您不需要保持每次重新分配新的内存,这确实有时间成本,无论是在初始内存分配中,还是在以后的垃圾收集中。