gpt4 book ai didi

go - Golang中的并发积分计算

转载 作者:IT王子 更新时间:2023-10-29 01:24:03 26 4
gpt4 key购买 nike

我尝试同时计算积分,但我的程序最终比使用普通 for 循环计算积分慢。我做错了什么?

package main

import (
"fmt"
"math"
"sync"
"time"
)

type Result struct {
result float64
lock sync.RWMutex
}

var wg sync.WaitGroup
var result Result

func main() {
now := time.Now()
a := 0.0
b := 1.0
n := 100000.0
deltax := (b - a) / n
wg.Add(int(n))
for i := 0.0; i < n; i++ {
go f(a, deltax, i)
}
wg.Wait()
fmt.Println(deltax * result.result)
fmt.Println(time.Now().Sub(now))
}

func f(a float64, deltax float64, i float64) {
fx := math.Sqrt(a + deltax * (i + 0.5))
result.lock.Lock()
result.result += fx
result.lock.Unlock()
wg.Done()
}

最佳答案

3- 为了提高性能,您可以在不使用 lock sync.RWMutex 的情况下按 CPU 内核划分任务:

+30x 使用 channel 和 runtime.NumCPU() 进行优化,这在 2 个内核上需要 2ms993µs 在 8 核上,而您的示例代码在 2 核上花费了 61ms,在 8 核上花费了 40ms:

查看此工作示例代码和输出:

package main

import (
"fmt"
"math"
"runtime"
"time"
)

func main() {
nCPU := runtime.NumCPU()
fmt.Println("nCPU =", nCPU)
ch := make(chan float64, nCPU)
startTime := time.Now()
a := 0.0
b := 1.0
n := 100000.0
deltax := (b - a) / n

stepPerCPU := n / float64(nCPU)
for start := 0.0; start < n; {
stop := start + stepPerCPU
go f(start, stop, a, deltax, ch)
start = stop
}

integral := 0.0
for i := 0; i < nCPU; i++ {
integral += <-ch
}

fmt.Println(time.Now().Sub(startTime))
fmt.Println(deltax * integral)
}

func f(start, stop, a, deltax float64, ch chan float64) {
result := 0.0
for i := start; i < stop; i++ {
result += math.Sqrt(a + deltax*(i+0.5))
}
ch <- result
}

2 核输出:

nCPU = 2
2.0001ms
0.6666666685900485

8 核输出:

nCPU = 8
993µs
0.6666666685900456

您的示例代码,2 核输出:

0.6666666685900424
61.0035ms

您的示例代码,8 核输出:

0.6666666685900415
40.9964ms

2- 要获得良好的基准统计数据,请使用大量样本(大 n):

正如您在此处看到的那样,使用 2 个内核,这在 2 个内核上需要 110ms,但在同一个 CPU 上使用 1 个内核,这需要 215msn := 10000000.0:

使用 n := 10000000.0 和单个 goroutine,请参阅此工作示例代码:

package main

import (
"fmt"
"math"
"time"
)

func main() {
now := time.Now()
a := 0.0
b := 1.0
n := 10000000.0
deltax := (b - a) / n
result := 0.0
for i := 0.0; i < n; i++ {
result += math.Sqrt(a + deltax*(i+0.5))
}
fmt.Println(time.Now().Sub(now))
fmt.Println(deltax * result)
}

输出:

215.0123ms
0.6666666666685884

使用 n := 10000000.0 和 2 个 goroutine,请参阅此工作示例代码:

package main

import (
"fmt"
"math"
"runtime"
"time"
)

func main() {
nCPU := runtime.NumCPU()
fmt.Println("nCPU =", nCPU)
ch := make(chan float64, nCPU)
startTime := time.Now()
a := 0.0
b := 1.0
n := 10000000.0
deltax := (b - a) / n

stepPerCPU := n / float64(nCPU)
for start := 0.0; start < n; {
stop := start + stepPerCPU
go f(start, stop, a, deltax, ch)
start = stop
}

integral := 0.0
for i := 0; i < nCPU; i++ {
integral += <-ch
}

fmt.Println(time.Now().Sub(startTime))
fmt.Println(deltax * integral)
}

func f(start, stop, a, deltax float64, ch chan float64) {
result := 0.0
for i := start; i < stop; i++ {
result += math.Sqrt(a + deltax*(i+0.5))
}
ch <- result
}

输出:

nCPU = 2
110.0063ms
0.6666666666686073

1- Goroutines 的数量存在一个最佳点,从这个点开始增加 Goroutines 的数量并不会减少程序的执行时间:

在 2 核 CPU 上,使用以下代码,结果是:

nCPU: 1,          2,          4,         8,           16
Time: 2.1601236s, 1.1220642s, 1.1060633s, 1.1140637s, 1.1380651s

如您所见,从 nCPU=1nCPU=2 时间减少足够大,但在这一点之后就不再多了,所以 nCPU=2 在 2 核 CPU 上是此示例代码的最佳点,因此在这里使用 nCPU := runtime.NumCPU() 就足够了。

package main

import (
"fmt"
"math"
"time"
)

func main() {
nCPU := 2 //2.1601236s@1 1.1220642s@2 1.1060633s@4 1.1140637s@8 1.1380651s@16
fmt.Println("nCPU =", nCPU)
ch := make(chan float64, nCPU)
startTime := time.Now()
a := 0.0
b := 1.0
n := 100000000.0
deltax := (b - a) / n

stepPerCPU := n / float64(nCPU)
for start := 0.0; start < n; {
stop := start + stepPerCPU
go f(start, stop, a, deltax, ch)
start = stop
}

integral := 0.0
for i := 0; i < nCPU; i++ {
integral += <-ch
}

fmt.Println(time.Now().Sub(startTime))
fmt.Println(deltax * integral)
}

func f(start, stop, a, deltax float64, ch chan float64) {
result := 0.0
for i := start; i < stop; i++ {
result += math.Sqrt(a + deltax*(i+0.5))
}
ch <- result
}

关于go - Golang中的并发积分计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39060899/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com