首页 文章

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

提问于
浏览
-2

我有一个名为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 回答

  • 3

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

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

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

  • 7

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

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

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

相关问题