0
votes

Given following code:

package main

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


func f(from string) {

    for i := 0; i < 3; i++ {
        fmt.Println(from, ":", i)
        //runtime.Gosched()
    }
}

func main() {

    runtime.GOMAXPROCS(runtime.NumCPU()*2)
    time.Sleep(100)

    go f("i am not parallel")

    go f("neither me")

    var input string
    fmt.Scanln(&input)
}

The output in most cases is:

i am not parallel : 0
i am not parallel : 1
i am not parallel : 2
neither me : 0
neither me : 1
neither me : 2

And sometimes:

neither me : 0
neither me : 1
neither me : 2
i am not parallel : 0
i am not parallel : 1
i am not parallel : 2

When runtime.Gosched() is uncommented all seems to be OK. I have tried changing GOMAXPROCS number from 2 to NumCPU, number of goroutines, cycles: none could get it to work in parallel.
Why so strange behaviour?

Edit: Ok, seems to be context-switching is heavy work and is not done very often without reasonable matters. One thing I still can't understand - why people get it to work without any sleep instructions?

1
you do just 3 println's in a row without intermediate delay. it seems quite reasonable that this little work is all down in a row. try adding a sleep after/before each println. switching between threads/processes is not free, thus it it is not done after every instruction.hoijui
@hoijui Yes, it works! But in examples that I found people didn't use any Sleep instructions and had printlns switching. Also I tried up to 100 cycles without sleep and it didn't work. When I try 400 and more - it switches but really not often. Maybe it is hardware-related issue?Le_Enot
i would say it is more software (kernel, used scheduling method) then hardware related, but yeah, also that. in general you should rely on the underlying system to do thread scheduling right, except you have very very good reason not to, and think you know better how to do scheduling then the people writing the OS kernel, for the performance of your application.hoijui

1 Answers

0
votes

you should not predict the goroutine schedule. by running the example you provided, I got this output.

direct : 0
direct : 1
direct : 2
goroutine : 0
goroutine : 1
goroutine : 2
going
done

if I add runtime.GOMAXPROCS(4) at the begin of main function, and run it on my i5 Qcore desktop ubuntu, it output

direct : 0
direct : 1
direct : 2
goroutine : 0
goroutine : 1
goroutine : 2
going

done

it not always produce same output I think. So we should assume goroutine may parallel, add lock if you need control the sequence.