尝试并行化但速度不够快。

huangapple go评论129阅读模式
英文:

Attempt to parallelize not fast enough

问题

我阅读了关于Go语言并发模型的文章,也了解了并发和并行的区别。为了测试并行执行,我编写了以下程序。

package main

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

const count = 1e8

var buffer [count]int

func main() {
	fmt.Println("GOMAXPROCS: ", runtime.GOMAXPROCS(0))

	// 初始化缓冲区
	for i := 0; i < count; i++ {
		buffer[i] = 3
	}

	// 顺序操作
	now := time.Now()
	worker(0, count-1)
	fmt.Println("顺序操作: ", time.Since(now))

	// 尝试并行化
	ch := make(chan int, 1)
	now = time.Now()
	go func() {
		worker(0, (count/2)-1)
		ch <- 1
	}()
	worker(count/2, count-1)
	<-ch
	fmt.Println("并行操作: ", time.Since(now))
}

func worker(start int, end int) {
	for i := start; i <= end; i++ {
		task(i)
	}
}

func task(index int) {
	buffer[index] = 2 * buffer[index]
}

但问题是:结果并不是很令人满意。

GOMAXPROCS:  8
顺序操作:  206.85ms
并行操作:  169.028ms

使用goroutine确实加快了速度,但并没有达到预期的两倍速度。我的代码和/或理解有什么问题?我该如何更接近两倍的速度?

英文:

I read about Go's concurrency model and also saw about the difference between concurrency and parallelism. In order to test parallel execution, I wrote the following program.

package main

import (
	&quot;fmt&quot;
	&quot;runtime&quot;
	&quot;time&quot;
)

const count = 1e8

var buffer [count]int

func main() {
	fmt.Println(&quot;GOMAXPROCS: &quot;, runtime.GOMAXPROCS(0))

	// Initialise with dummy value
	for i := 0; i &lt; count; i++ {
		buffer[i] = 3
	}

	// Sequential operation
	now := time.Now()
	worker(0, count-1)
	fmt.Println(&quot;sequential operation: &quot;, time.Since(now))

	// Attempt to parallelize
	ch := make(chan int, 1)
	now = time.Now()
	go func() {
		worker(0, (count/2)-1)
		ch &lt;- 1
	}()
	worker(count/2, count-1)
	&lt;-ch
	fmt.Println(&quot;parallel operation: &quot;, time.Since(now))
}

func worker(start int, end int) {
	for i := start; i &lt;= end; i++ {
		task(i)
	}
}

func task(index int) {
	buffer[index] = 2 * buffer[index]
}

But the problem is: the results are not very pleasing.

GOMAXPROCS:  8
sequential operation:  206.85ms
parallel operation:  169.028ms

Using a goroutine does speed things up but not enough. I expected it to be closer to being twice as fast. What is wrong with my code and/or understanding? And how can I get closer to being twice as fast?

答案1

得分: 2

并行化是强大的,但在如此小的计算负载下很难看到效果。以下是一个具有更大结果差异的示例代码:

package main

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

func calctest(nCPU int) {
	fmt.Println("协程数:", 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
}

func main() {
	nCPU := runtime.NumCPU()
	calctest(nCPU)
    fmt.Println("")
	calctest(1)
}

这是我得到的结果:

协程数: 8
853.181μs

协程数: 1
2.031358ms
英文:

Parallelization is powerful, but it's hard to see with such a small computational load. Here is some sample code with a larger difference in the result:

package main

import (
	&quot;fmt&quot;
	&quot;math&quot;
	&quot;runtime&quot;
	&quot;time&quot;
)

func calctest(nCPU int) {
	fmt.Println(&quot;Routines:&quot;, 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 &lt; n; {
		stop := start + stepPerCPU
		go f(start, stop, a, deltax, ch)
		start = stop
	}

	integral := 0.0
	for i := 0; i &lt; nCPU; i++ {
		integral += &lt;-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 &lt; stop; i++ {
		result += math.Sqrt(a + deltax*(i+0.5))
	}
	ch &lt;- result
}

func main() {
	nCPU := runtime.NumCPU()
	calctest(nCPU)
    fmt.Println(&quot;&quot;)
	calctest(1)
}

This is the result I get:

Routines: 8
853.181&#181;s

Routines: 1
2.031358ms

huangapple
  • 本文由 发表于 2021年7月9日 21:21:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/68317510.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定