为了账号安全,请及时绑定邮箱和手机立即绑定

不同输入数据的 Goroutine 执行时间

不同输入数据的 Goroutine 执行时间

Go
繁花不似锦 2021-08-23 17:54:15
我正在尝试使用 goroutine 来并行化一些计算。但是,goroutine 的执行时间让我很困惑。我的实验设置很简单。runtime.GOMAXPROCS(3)datalen := 1000000000data21 := make([]float64, datalen)data22 := make([]float64, datalen)data23 := make([]float64, datalen)t := time.Now()res := make(chan interface{}, dlen)go func() {    for i := 0; i < datalen; i++ {        data22[i] = math.Sqrt(13)    }    res <- true}()go func() {    for i := 0; i < datalen; i++ {        data22[i] = math.Sqrt(13)    }    res <- true}()go func() {    for i := 0; i < datalen; i++ {        data22[i] = math.Sqrt(13)    }    res <- true}()for i:=0; i<3; i++ {    <-res}fmt.Printf("The parallel for loop took %v to run.\n", time.Since(t))请注意,我在 3 个 goroutine 中加载了相同的数据,该程序的执行时间为The parallel for loop took 7.436060182s to run.但是,如果我让每个 goroutine 处理不同的数据,如下所示:runtime.GOMAXPROCS(3)datalen := 1000000000data21 := make([]float64, datalen)data22 := make([]float64, datalen)data23 := make([]float64, datalen)t := time.Now()res := make(chan interface{}, dlen)go func() {    for i := 0; i < datalen; i++ {        data21[i] = math.Sqrt(13)    }    res <- true}()go func() {    for i := 0; i < datalen; i++ {        data22[i] = math.Sqrt(13)    }    res <- true}()go func() {    for i := 0; i < datalen; i++ {        data23[i] = math.Sqrt(13)    }    res <- true}()for i:=0; i<3; i++ {    <-res}fmt.Printf("The parallel for loop took %v to run.\n", time.Since(t))这个的执行时间几乎是之前的 3 倍,几乎等于/比没有 goroutine 的顺序执行更糟The parallel for loop took 20.744438468s to run.我想也许我以错误的方式使用了 goroutine。那么使用多个 goroutine 处理不同数据的正确方法应该是什么?
查看完整描述

2 回答

?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

由于您的示例程序没有执行任何实质性的计算,瓶颈将是数据写入内存的速度。使用示例中的设置,我们讨论的是 22 GB 的写入,这并不是无关紧要的。

鉴于两个示例的运行时间存在时间差异,一种可能的可能性是它实际上没有向 RAM 写入那么多。鉴于内存写入由 CPU 缓存,执行可能如下所示:

  1. 第一个 goroutine 将数据写入表示data22数组开头的缓存行。

  2. 第二个 goroutine 将数据写入表示相同位置的缓存行。运行第一个 goroutine 的 CPU 注意到写入使自己缓存的写入无效,因此丢弃其更改。

  3. 第三个 goroutine 将数据写入表示相同位置的缓存行。运行第二个 goroutine 的 CPU 注意到写入使自己缓存的写入无效,因此丢弃其更改。

  4. 第三个 CPU 中的缓存行被逐出,并将更改写出到 RAM。

这个过程随着 goroutine 在data22数组中的进展而继续。由于 RAM 是瓶颈,在这种情况下我们最终写入的数据量是后者的三分之一,因此它的运行速度大约是第二种情况的 3 倍也就不足为奇了。


查看完整回答
反对 回复 2021-08-23
?
心有法竹

TA贡献1866条经验 获得超5个赞

您正在使用大量内存。在第一个示例中 1000000000 * 8 = 8GB,在第二个示例中 3 * 1000000000 * 8 = 24GB。在第二个示例中,您可能使用了大量交换空间。磁盘 I/O 非常非常慢,即使在 SSD 上也是如此。

将 datalen := 1000000000 更改为 datalen := 100000000,减少 10 倍。你现在的运行时间是多少?每个示例至少平均运行 3 次。你的电脑有多少内存?你用的是SSD吗?


查看完整回答
反对 回复 2021-08-23
  • 2 回答
  • 0 关注
  • 194 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信