为什么并发代码需要更多时间来执行

时间:2015-04-30 09:35:10

标签: multithreading concurrency go

我有一个名为linearize的函数......我试图加快执行速度,但却惊讶地发现它变慢了。我错过了什么或搞砸了基本面......

根据我的理解,事情应该有所改善..

谢谢,

package main

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

var rgb []float64

func linearizeWithWg(v float64, idx int, wg *sync.WaitGroup) {
    defer wg.Done()

    if v <= 0.04045 {
        rgb[idx] = v / 12.92
    } else {
        rgb[idx] = math.Pow((v+0.055)/1.055, 2.4)
    }
}

func linearizeWithGoR(v float64) float64 {
    res := make(chan float64)

    go func(input float64) {
        if input <= 0.04045 {
            res <- input / 12.92
        } else {
            res <- math.Pow((input+0.055)/1.055, 2.4)
        }
    }(v)
    return <-res
}

func linearizeNomal(v float64) float64 {
    if v <= 0.04045 {
        return v / 12.92
    }
    return math.Pow((v+0.055)/1.055, 2.4)
}

func main() {
    start := time.Now()
    const C = 1.0 / 255.0

    //Normal Execution
    for i := 0; i < 100000; i++ {
        linearizeNomal(float64(i) * C * 0.5)
        linearizeNomal(float64(i) * C * 1.5)
        linearizeNomal(float64(i) * C * 4.5)
    }
    elaspsed := time.Since(start)
    fmt.Println(elaspsed)

    //With GoRoutines.. Slow
    start = time.Now()
    for i := 0; i < 100000; i++ {
        linearizeWithGoR(float64(i) * C * 0.5)
        linearizeWithGoR(float64(i) * C * 1.5)
        linearizeWithGoR(float64(i) * C * 2.5)
    }
    elaspsed = time.Since(start)
    fmt.Println(elaspsed)

    //With WaitGroup. Slow

    for i := 0; i < 100000; i++ {
        rgb = make([]float64, 3)
        var wg sync.WaitGroup
        wg.Add(3)
        linearizeWithWg(float64(i)*C*0.5, 0, &wg)
        linearizeWithWg(float64(i)*C*1.5, 1, &wg)
        linearizeWithWg(float64(i)*C*4.5, 2, &wg)
        wg.Wait()
    }
    elaspsed = time.Since(start)
    fmt.Println(elaspsed)

}

2 个答案:

答案 0 :(得分:7)

所有与并发相关的函数(通道创建,通道发送,goroutine创建)的开销远大于您在每个goroutine中执行的两条指令。

此外,您的goroutine版本基本上是串行版本,因为您生成了goroutine并立即等待其频道的结果。 waitgroup版本类似。

再次尝试使用少量goroutine,每个goroutine执行一个循环块。 @Joker_vD也有一个很好的点,以确保GOMAXPROCS大于一。

答案 1 :(得分:3)

你的问题是你实际上并没有同时做任何事情。

在工作组示例中,您需要调用go linearizeWithWg(...)

在goroutine示例中,您启动了一个goroutine,然后等待它在函数中结束。要同时运行它,您需要一个缓冲的响应通道,并让另一个goroutine获得响应