matrix - `matrix * vector`、 `matrix’ * vector` 和 `copy(matrix’ ) * vector` 之间的非直观性能差异

标签 matrix julia

问题来自 Julia Discourse

我正在使用 Julia 1.2。这是我的测试:

a = rand(1000, 1000)
b = adjoint(a)
c = copy(b)

@btime a * x setup=(x=rand(1000)) # 114.757 μs
@btime b * x setup=(x=rand(1000)) # 94.179 μs
@btime c * x setup=(x=rand(1000)) # 110.325 μs

我在期待 c 至少不会变慢。

检查后 stdlib/LinearAlgebra/src/matmul.jl ,事实证明 Julia 通过了 b.parent (即 a )到 BLAS.gemv ,不是 b ,而是切换 LAPACK 的 dgemv_ 进入一种不同且明显更快的模式。

我是否正确假设加速来自这样一个事实,即内存以更有利的方式对齐 dgemv_ 确实,当它在 中时反式 = T 模式?如果是这样,那么我猜这不是可行的,除了可能以某种方式在文档中提及问题。如果我的假设是错误的,有什么可以做的吗?

最佳答案

@stevengj 在同一个 Discourse 帖子中的回答:

Am I correct in assuming that the speedup comes from the fact that the memory is aligned in a more favorable way for whatever dgemv_ does, when it’s in a trans = T mode?



关闭。它确实与内存有关,但它是关于 locality ,不对齐。要理解的基本事情是,由于 cache lines 的存在,从内存中访问连续(或至少附近)数据比从内存中访问数据更有效。 . (连续访问在使用 SIMD 指令方面也有一些优势。)

Julia 将矩阵存储在 column-major order 中,以便列在内存中是连续的。因此,当您将转置矩阵(尚未复制的)乘以向量时,它可以将其计算为连续列(= 转置行)与连续向量的点积,其具有良好的 空间局部性因此可以有效地利用缓存行。

相比之下,要将非转置矩阵乘以向量,您将矩阵的非连续行的点积与向量相乘,并且更难有效利用缓存行。在这种情况下,为了改善空间局部性,像 OpenBLAS 这样的优化 BLAS 实际上一次计算多行(一个“块”)与向量的点积,我相信——这就是为什么它只慢了 10% 而不是更糟。 (事实上​​,即使是转置的情况也可能会做一些阻塞以将向量保持在缓存中。)

关于matrix - `matrix * vector`、 `matrix’ * vector` 和 `copy(matrix’ ) * vector` 之间的非直观性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58126704/

相关文章:

python - 无法将 numpy 二维数组保存到文件中

c - 在C中使用多线程做矩阵乘法

r - 通过 R 中的矩阵列表进行索引

arrays - 将矩阵并排放置以创建另一个矩阵

julia - Julia 的 GLM 可以进行加权最小二乘吗?

python - 使用 numpys np.fromfunction 评估 Python lambda 函数

julia - 了解 Julia 中的告诫

amazon-s3 - Julia 从 s3 csv 文件加载数据框

algorithm - 在 Julia 中设置算法的时间限制

Julia 不是运算符