当打印时间消耗时,goroutines会相互影响。

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

goroutines affect each other when printing timecost

问题

我是一名Golang的新手。我知道goroutine是一个抽象的CPU和内存组合,用于运行一段代码。

所以当我在goroutine中运行一些计算函数(比如排序)时,我希望它们能够并行运行。但是打印出来的结果似乎很奇怪,"并行"的代码几乎同时打印出相同的时间消耗。

为什么会这样?是我对goroutine有什么误解,还是因为printTime()函数的原因?

代码:https://play.golang.org/p/n9DLn57ftM

附注:代码应该复制到本地的go文件中运行。在play.golang中运行有一些限制。

结果是:

MaxProcs: 8

Source : 2.0001ms
Quick sort : 3.0002ms
Merge sort : 8.0004ms
Insertion sort : 929.0532ms
Goroutine num: 1

Source : 2.0001ms
Goroutine num: 4

Insertion sort : 927.0531ms
Quick sort : 930.0532ms
Merge sort : 934.0535ms
英文:

I'm a freshman for Golang. I know goroutine is an abstract group of cpu and memory to run a piece of code.

So When I run some computing funcs(like sort) in goroutines, I'm hoping they run parallel. But the printed result seems weird, the "paralell" codes print nearly the same timecost.

Why? Is there something I missed about goroutine, or it's because of the func printTime() ?

codes: https://play.golang.org/p/n9DLn57ftM

P.S. codes should be copied to local go file and run. Those run in play.golang has some limitation.

the result is:

MaxProcs: 8

Source : 2.0001ms
Quick sort : 3.0002ms
Merge sort : 8.0004ms
Insertion sort : 929.0532ms
Goroutine num: 1

Source : 2.0001ms
Goroutine num: 4

Insertion sort : 927.0531ms
Quick sort : 930.0532ms
Merge sort : 934.0535ms

答案1

得分: 1

你应该测量总时间成本,而不是每个排序算法所需的单个时间成本。当任务分布到多个goroutine时,单个时间成本可能会更长,因为需要额外的时间来设置goroutine。根据程序的性质,可能需要额外的时间来进行goroutine之间和/或与主进程的通信。有一些与goroutine相关的资源,例如:

  1. https://stackoverflow.com/questions/18058164/is-a-go-goroutine-a-coroutine
  2. http://divan.github.io/posts/go_concurrency_visualize/

如果你将main函数改为:

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

    start := time.Now()
    sequentialTest()
    seq := time.Now()
    concurrentTest()
    con := time.Now()

    fmt.Printf("\n\nCalculation time, sequential: %v, concurrent: %v\n",
        seq.Sub(start), con.Sub(seq))
}

输出将会是:

MaxProcs: 4

Source : 3.0037ms
Quick sort : 5.0034ms
Merge sort : 13.0069ms
Insertion sort : 1.2590941s
Goroutine num: 1

Source : 3.0015ms
Goroutine num: 4

Insertion sort : 1.2399076s
Quick sort : 1.2459121s
Merge sort : 1.2519156s

Calculation time, sequential: 1.2831112s, concurrent: 1.2559194s

移除printTime后,输出将会是:

MaxProcs: 4
Goroutine num: 1
Goroutine num: 4

Calculation time, sequential: 1.3154314s, concurrent: 1.244112s

时间成本的值可能会略有变化,但大多数情况下结果将是sequential > concurrent。总之,将任务分布到多个goroutine中可能会增加整体性能(时间成本),但不会增加单个任务的性能。

英文:

You should measure total time cost instead of individual time cost required by each sorting algorithm. The individual time cost might be longer when the task is distributed into several goroutines since it need additional time to setup the goroutine. Depending on the nature of your program, additional time might be needed for communication between goroutine and/or with main process. There're some resources related to goroutine, e.g.

  1. https://stackoverflow.com/questions/18058164/is-a-go-goroutine-a-coroutine
  2. http://divan.github.io/posts/go_concurrency_visualize/

If you change main function to:

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

    start := time.Now()
    sequentialTest()
    seq := time.Now()
    concurrentTest()
    con := time.Now()

    fmt.Printf("\n\nCalculation time, sequential: %v, concurrent: %v\n",
        seq.Sub(start), con.Sub(seq))
}

the output will look like:

MaxProcs: 4

Source : 3.0037ms
Quick sort : 5.0034ms
Merge sort : 13.0069ms
Insertion sort : 1.2590941s
Goroutine num: 1

Source : 3.0015ms
Goroutine num: 4

Insertion sort : 1.2399076s
Quick sort : 1.2459121s
Merge sort : 1.2519156s

Calculation time, sequential: 1.2831112s, concurrent: 1.2559194s

After removing printTime, it looks like:

MaxProcs: 4
Goroutine num: 1
Goroutine num: 4

Calculation time, sequential: 1.3154314s, concurrent: 1.244112s

The time cost value might change slightly, but most of the time the result will be sequential > concurrent. In summary, distributing the task into several goroutines, may increase the overall performance (time cost) but not the individual task.

答案2

得分: 0

抱歉,我不理解你想要测试什么。首先,你的代码在快速排序部分不起作用,因为你使用 go quickSort(...) 来运行快速排序。

wg.Add(1)
go func(){
    go quickSort(s1, nil)
    wg.Done()
}()

这个 goroutine 会立即退出。
现在,我已经测试了你的代码,并且我注意到你必须在开始和全部完成之间获取总时间。

这里 是你的代码。

英文:

Sorry, I don't understand what you want to test. At the first, you code doesn't work for quickSort because you run quickSort with go quickSort(...).

wg.Add(1)
go func(){
    go quickSort(s1, nil)
    wg.Done()
}()

This goroutine will quit immediately.
Now, I tested your code. And I notice that you must get total time between start and all of finish.

https://play.golang.org/p/O8Gj-OYIdR

答案3

得分: 0

wg.Add(1)
go func(){
go quickSort(s1, nil)
wg.Done()
}()

你不需要第二个go

应该是这样的

wg.Add(1)
go func(){
quickSort(s1, nil)
wg.Done()
}()

发生的情况是go func()启动了一个goroutine,而go quickSort(s1, nil)启动了另一个goroutine。结果是,wg.Done()(以及因此wg.Done())几乎立即执行(而不等待quickSort)。

英文:
wg.Add(1)
go func(){
    go quickSort(s1, nil)
    wg.Done()
}()

You don't need that second go

It should be like

wg.Add(1)
go func(){
    quickSort(s1, nil)
    wg.Done()
}()

What happened is that go func() started one goroutine, and go quickSort(s1, nil) starts another. As a result, wg.Done() (and, as a result, wg.Done()) gets executed practically right away (without waiting for quickSort).

huangapple
  • 本文由 发表于 2017年6月29日 10:23:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/44815367.html
匿名

发表评论

匿名网友

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

确定