我正在通过 Go 中的 goroutines 优化矩阵乘法。我的基准测试显示,每行或每元素引入并发会大大降低性能:goos: darwin
goarch: amd64
BenchmarkMatrixDotNaive/A.MultNaive-8 2000000 869 ns/op 0 B/op 0 allocs/op
BenchmarkMatrixDotNaive/A.ParalMultNaivePerRow-8 100000 14467 ns/op 80 B/op 9 allocs/op
BenchmarkMatrixDotNaive/A.ParalMultNaivePerElem-8 20000 77299 ns/op 528 B/op 65 allocs/op我知道缓存局部性的一些基本先验知识,每个元素并发性降低性能是有道理的。但是,为什么即使在原始版本中每行仍然会降低性能?事实上,我还写了一个 block/tiling optimization,它的 vanilla 版本(没有 goroutine 并发)甚至比 naive 版本更差(这里不存在,让我们先关注 naive)。我在这里做错了什么?为什么?这里怎么优化?
1 回答
慕桂英546537
TA贡献1848条经验 获得超10个赞
执行 8x8 矩阵乘法是相对较小的工作。
Goroutines(虽然可能是轻量级的)确实有开销。如果他们所做的工作是“小”的,那么启动、同步和丢弃它们的开销可能会超过利用多核/线程的性能增益,并且总体而言,您可能无法通过并发执行此类小任务来获得性能(见鬼,您可能甚至比不使用 goroutines 更糟糕)。措施。
如果我们将矩阵大小增加到 80x80,运行基准测试,我们已经看到在以下情况下有一些性能提升ParalMultNaivePerRow
:
BenchmarkMatrixDotNaive/A.MultNaive-4 2000 1054775 ns/op BenchmarkMatrixDotNaive/A.ParalMultNaivePerRow-4 2000 709367 ns/op BenchmarkMatrixDotNaive/A.ParalMultNaivePerElem-4 100 10224927 ns/op
(正如您在结果中看到的,我有 4 个 CPU 内核,在您的 8 核机器上运行它可能会显示出更多的性能提升。)
当行很小时,您正在使用 goroutines 来完成最少的工作,您可以通过在 goroutines 完成“微小”工作后不“丢弃”它们来提高性能,但您可以“重用”它们。
- 1 回答
- 0 关注
- 97 浏览
添加回答
举报
0/150
提交
取消