3 回答
TA贡献1877条经验 获得超6个赞
使用并发并不一定会使算法运行得更快。事实上,除非算法本质上是并行的,否则它会减慢执行速度。
处理器 (CPU) 一次只能做一件事,即使对我们来说,它似乎同时做两件事。两个 goroutine 的指令可能会交错,但这并不会使它们运行得比单个 goroutine 快。在任何给定时刻都只执行来自一个 goroutine 的一条指令(有一些非常低级别的异常,具体取决于硬件特性)——除非您的程序在多个内核上运行。
据我所知,标准归并排序算法本质上并不是并行的;需要进行一些修改以优化它以在多个处理器上并行执行。即使您使用多个处理器,也需要针对它优化算法。
这些优化通常与通道的使用有关。我不同意“写入通道有很大的开销”本身(Go 使它非常高效),但是,它确实引入了 goroutine 阻塞的可能性。显着减慢程序速度的不是对通道的实际写入,而是调度/同步:等待和唤醒 goroutine 以从通道写入或读取可能是瓶颈。
为了补充 Not_a_Golfer 的回答,我同意 goroutine 在执行 I/O 操作时肯定会发光——即使在单个内核上——因为这些发生在远离 CPU 的地方。当一个 goroutine 正在等待 I/O 时,调度程序可以调度另一个受 CPU 限制的 goroutine 在此期间运行。然而,当跨多个处理器/内核部署时,goroutines 也适用于 CPU 密集型操作。
TA贡献1815条经验 获得超13个赞
正如其他人所解释的,并行是有代价的。您需要看到足够的收益来补偿该成本。这仅在工作单元大于制作通道和 goroutine 接收结果的成本时才会发生。
您可以通过试验来确定工作单元应该是什么。假设工作单元对 1000 个元素进行排序。在这种情况下,您可以非常轻松地更改代码,如下所示:
func MergeSortAsync(numbers [] int, resultChan chan []int) {
l := len(numbers)
if l <= 1000 {
resultChan <- Mergesort(numbers)
return
}
换句话说,一旦工作单元太小而无法证明使用 goroutines 和通道是合理的,那么使用你的 simpleMergesort没有这些成本。
TA贡献1815条经验 获得超6个赞
有两个主要原因:
写入通道有很大的开销。作为参考 - 我尝试使用通道和 goroutines 作为迭代器。它们比重复调用方法慢约 100 倍。当然,如果通过管道传输的操作需要很长时间才能执行(例如抓取网页),则这种差异可以忽略不计。
Goroutines 在基于 IO 的并发性方面非常出色,而在 CPU 并行性方面则不然。
考虑到这两个问题,您将需要大量 CPU 或更长时间,每个 goroutine 的阻塞操作更少,以使其更快。
- 3 回答
- 0 关注
- 171 浏览
添加回答
举报