Goroutines don';t线性扩展,但Go程序可以吗?

Goroutines don';t线性扩展,但Go程序可以吗?,go,Go,我正在寻找一些关于性能优化的一般建议 我有一段相当复杂的代码,但是代码存在于一个函数中(没有全局函数),所以我可以a)在多个goroutine中调用这个函数(我的机器上有12个内核)。或者b)使用一次调用的相同类型的函数,编译我的go程序并并行运行整个程序4次 下面是具有相同行为的示例代码: package main import ( "fmt" "runtime" "time" ) const size = 140000 type BigStruct struct

我正在寻找一些关于性能优化的一般建议

我有一段相当复杂的代码,但是代码存在于一个函数中(没有全局函数),所以我可以a)在多个goroutine中调用这个函数(我的机器上有12个内核)。或者b)使用一次调用的相同类型的函数,编译我的go程序并并行运行整个程序4次

下面是具有相同行为的示例代码:

package main

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

const size = 140000

type BigStruct struct {
    first  []int
    second []int
}

func slowFunc() int {
    // make local variables
    sum := 0
    myData := BigStruct{}
    myData.first = make([]int, 0, size)

    // fill some slices 
    for i := 0; i < size; i++ {
        myData.first = append(myData.first, i)
        myData.second = append(myData.second, i)
    }

    // do pointless calculations
    for i := range myData.first {
        for j := range
            myData.second {
            if myData.first[i] == myData.second[j] {
                sum++
            }
        }

    }
    return sum
}

func slowFuncChan(output chan int) {
    // make local variables
    sum := 0
    myData := BigStruct{}
    myData.first = make([]int, 0, size)

    // fill some slices 
    for i := 0; i < size; i++ {
        myData.first = append(myData.first, i)
        myData.second = append(myData.second, i)
    }

    // do pointless calculations
    for i := range myData.first {
        for j := range
            myData.second {
            if myData.first[i] == myData.second[j] {
                sum++
            }
        }

    }
    output <- sum
}

func main() {

    numCPUs := runtime.NumCPU()
    runtime.GOMAXPROCS(numCPUs)
    fmt.Println("numCPUs: ", numCPUs)

    fmt.Println("Calling slowFunc once...")

    start := time.Now()
    fmt.Println("sum: ", slowFunc())
    t := time.Now() // test
    elapsed := t.Sub(start)
    fmt.Println("time elapsed: ", elapsed)
    fmt.Println()


    fmt.Println("Calling slowFunc 4x in goroutines...")

    output := make(chan int, 4)
    for w := 0; w < 4; w++ {
        go slowFuncChan(output)
    }

    for a := 0; a < 4; a++ {
        fmt.Println("sum: ", <-output)
    }

    t2 := time.Now() // test
    elapsed = t2.Sub(t)
    fmt.Println("time elapsed: ", elapsed)
}
使用批处理文件,我同时启动程序4次,得到以下4个结果:

numCPUs:  12
Calling slowFunc once...
sum:  140000
time elapsed:  12.7615683s
,

,

,

同时运行4个程序的总时间为12.7705668秒,几乎是goroutines版本(22.4335858秒)的一半


我用8个goroutine和8个同时运行的程序对此进行了测试,得到了相同的结果,多个应用程序运行的goroutine版本是单个goroutine版本的2倍。

您如何衡量执行这两个场景的时间?如果您的功能确实不访问共享数据,也没有IO,并且没有启动更多goroutine,4个goroutine应该大致在同一时间内完成。如果不看到代码的其他行为,就不可能进一步帮助您。启动应用程序4次(每次启动1个goroutine)会产生大量开销,性能会更差。@Cerise函数调用大约需要1.5秒,因此我打印了一个简单的时间差。Now()以获得估计值。@DavidNg这也表明,一个应用程序有4个goroutine,性能会更好(一次性加载那个大结构就足够了)。我们应该真正了解您的代码,或者提出一个。添加一个示例。您如何衡量执行这两个场景的时间?如果您的函数确实不访问共享数据,也不执行IO,并且不启动进一步的goroutine,那么4个goroutine应该大致在同一时间内完成。如果不看到代码的其他行为,就不可能进一步帮助您。启动应用程序4次(每次启动1个goroutine)会产生大量开销,性能会更差。@Cerise函数调用大约需要1.5秒,因此我打印了一个简单的时间差。Now()以获得估计值。@DavidNg这也表明,一个应用程序有4个goroutine,性能会更好(一次性加载那个大结构就足够了)。我们真的应该看看你的代码,或者想出一个。添加了一个例子。
numCPUs:  12
Calling slowFunc once...
sum:  140000
time elapsed:  12.7615683s
numCPUs:  12
Calling slowFunc once...
sum:  140000
time elapsed:  12.7705668s
numCPUs:  12
Calling slowFunc once...
sum:  140000
time elapsed:  12.2635664s
numCPUs:  12
Calling slowFunc once...
sum:  140000
time elapsed:  12.1155655s