猿问

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

我正在尝试使用 goroutine 来并行化一些计算。但是,goroutine 的执行时间让我很困惑。我的实验设置很简单。


runtime.GOMAXPROCS(3)


datalen := 1000000000

data21 := 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 := 1000000000

data21 := 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 处理不同数据的正确方法应该是什么?


繁花不似锦
浏览 197回答 2
2回答

幕布斯7119047

由于您的示例程序没有执行任何实质性的计算,瓶颈将是数据写入内存的速度。使用示例中的设置,我们讨论的是 22 GB 的写入,这并不是无关紧要的。鉴于两个示例的运行时间存在时间差异,一种可能的可能性是它实际上没有向 RAM 写入那么多。鉴于内存写入由 CPU 缓存,执行可能如下所示:第一个 goroutine 将数据写入表示data22数组开头的缓存行。第二个 goroutine 将数据写入表示相同位置的缓存行。运行第一个 goroutine 的 CPU 注意到写入使自己缓存的写入无效,因此丢弃其更改。第三个 goroutine 将数据写入表示相同位置的缓存行。运行第二个 goroutine 的 CPU 注意到写入使自己缓存的写入无效,因此丢弃其更改。第三个 CPU 中的缓存行被逐出,并将更改写出到 RAM。这个过程随着 goroutine 在data22数组中的进展而继续。由于 RAM 是瓶颈,在这种情况下我们最终写入的数据量是后者的三分之一,因此它的运行速度大约是第二种情况的 3 倍也就不足为奇了。

心有法竹

您正在使用大量内存。在第一个示例中 1000000000 * 8 = 8GB,在第二个示例中 3 * 1000000000 * 8 = 24GB。在第二个示例中,您可能使用了大量交换空间。磁盘 I/O 非常非常慢,即使在 SSD 上也是如此。将 datalen := 1000000000 更改为 datalen := 100000000,减少 10 倍。你现在的运行时间是多少?每个示例至少平均运行 3 次。你的电脑有多少内存?你用的是SSD吗?
随时随地看视频慕课网APP

相关分类

Go
我要回答