【发布时间】:2023-03-10 09:32:02
【问题描述】:
我在 Java 中编写了两个矩阵类,只是为了比较它们的矩阵乘法的性能。一个类 (Mat1) 存储一个 double[][] A 成员,其中矩阵的行 i 是 A[i]。另一个类(Mat2)存储A 和T,其中T 是A 的转置。
假设我们有一个方阵 M,我们想要 M.mult(M) 的乘积。致电产品P。
当 M 是 Mat1 实例时,使用的算法很简单:
P[i][j] += M.A[i][k] * M.A[k][j]
for k in range(0, M.A.length)
在 M 是我使用的 Mat2 的情况下:
P[i][j] += M.A[i][k] * M.T[j][k]
这是与T[j][k]==A[k][j] 相同的算法。在 1000x1000 矩阵上,第二个算法在我的机器上大约需要 1.2 秒,而第一个算法至少需要 25 秒。我期待第二个更快,但不是这么快。问题是,为什么会这么快?
我唯一的猜测是第二种算法更好地利用了 CPU 缓存,因为数据以大于 1 个字的块的形式被拉入缓存,第二种算法通过仅遍历行而受益,而第一种算法忽略了数据通过立即转到下面的行(在内存中大约 1000 个字,因为数组按行主要顺序存储)被拉入缓存,没有任何数据被缓存。
我问了一个人,他认为这是因为更友好的内存访问模式(即第二个版本会导致更少的 TLB 软故障)。我完全没有想到这一点,但我可以看出它是如何减少 TLB 错误的。
那么,它是什么?还是有其他原因导致性能差异?
【问题讨论】:
-
我认为您可能会对这个堆栈交换proposal 感兴趣。如果它是显示您的支持并帮助它进入测试版。
标签: java performance matrix-multiplication