Skip to content

runtime: Strange behavior about GOMAXPROCS and GOMAXPROCS in environment #9750

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
denghongcai opened this issue Feb 2, 2015 · 8 comments
Closed

Comments

@denghongcai
Copy link

I met a problem about the different behavior about runtime.GOMAXPROCS and GOMAXPROCS in environment.
The golang version I use is:

go version go1.4.1 linux/amd64

The OS is:

Linux  3.13.0-44-generic #73-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux

The test code I use is as follow:

package main

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

func f1() {
        for {
        }
}      

func f2() {
        for {
                fmt.Println("foo")
                time.Sleep(time.Second)
        }
}      

func main() {
        runtime.GOMAXPROCS(runtime.NumCPU())
        go f1()
        go f2()
        for {
                fmt.Println("main")
                time.Sleep(time.Second)
        }
}      

When I set GOMAXPROCS using runtime.GOMAXPROCS,the result of this program is it hang on

go f2()

But if I set GOMAXPROCS using

export GOMAXPROCS=4

it works just fine.

So I turn on the GODEBUG macro and set schedtrace=1000, run the program again, I got different log.

Using environment:

SCHED 0ms: gomaxprocs=4 idleprocs=3 threads=2 spinningthreads=0 idlethreads=0 runqueue=0 [1 0 0 0]
main
foo
main
foo
SCHED 1007ms: gomaxprocs=4 idleprocs=3 threads=5 spinningthreads=0 idlethreads=2 runqueue=0 [0 0 0 0]
foo
main
SCHED 2014ms: gomaxprocs=4 idleprocs=3 threads=5 spinningthreads=0 idlethreads=2 runqueue=0 [0 0 0 0]
foo
main
SCHED 3020ms: gomaxprocs=4 idleprocs=3 threads=5 spinningthreads=0 idlethreads=2 runqueue=0 [0 0 0 0]

Using runtime.GOMAXPROCS:

SCHED 0ms: gomaxprocs=1 idleprocs=0 threads=2 spinningthreads=0 idlethreads=0 runqueue=0 [1]
SCHED 1000ms: gomaxprocs=4 idleprocs=0 threads=5 spinningthreads=0 idlethreads=2 runqueue=1 [0 0 0 0]
SCHED 2006ms: gomaxprocs=4 idleprocs=0 threads=5 spinningthreads=0 idlethreads=2 runqueue=1 [0 0 0 0]
SCHED 3011ms: gomaxprocs=4 idleprocs=0 threads=5 spinningthreads=0 idlethreads=2 runqueue=1 [0 0 0 0]
SCHED 4019ms: gomaxprocs=4 idleprocs=0 threads=5 spinningthreads=0 idlethreads=2 runqueue=1 [0 0 0 0]
SCHED 5024ms: gomaxprocs=4 idleprocs=0 threads=5 spinningthreads=0 idlethreads=2 runqueue=1 [0 0 0 0]
SCHED 6030ms: gomaxprocs=4 idleprocs=0 threads=5 spinningthreads=0 idlethreads=2 runqueue=1 [0 0 0 0]

Sometimes, runtime.GOMAXPROCS will cause whole program spining. I can't find any suggestions about this situation I met, maybe it's a bug?

@dvyukov
Copy link
Member

dvyukov commented Feb 2, 2015

You are collecting sched trace from go tool itself (it is also written in Go).
Build the program and then run the binary with GODEBUG=schedtrace

@denghongcai
Copy link
Author

Sorry for my big mistake, I change my description if you have any further suggestion, thanks.

@dvyukov
Copy link
Member

dvyukov commented Feb 2, 2015

It is for{} that makes the program to hang.
for {} is always bad, and makes any real program hang. Remove for{} and both variants will work.

@denghongcai
Copy link
Author

Sure, I do know that for in goroutine without runtime.Gosched() is evil. I just want to know why two ways on setting GOMAXPROCS is different, I'm always thinking it is === before. In some situation we have to do some math thing in goroutine, and I wonder this may cause some problem here.

@mikioh mikioh changed the title Strange behavior about runtime.GOMAXPROCS and GOMAXPROCS in environment runtime: Strange behavior about GOMAXPROCS and GOMAXPROCS in environment Feb 2, 2015
@dvyukov
Copy link
Member

dvyukov commented Feb 2, 2015

The behavior is different because scheduling is slightly different. But the version that currently works is not guaranteed to work in future. Moreover, if you trigger a GC or call runtime.GOMAXPROCS when a goroutine is already spinning both versions will hang (runtime needs stop all goroutines).

Finite amount of math is fine. Especially if it makes any function calls, because function calls are preemption points. Infinite amount of math without any function calls is a problem whatever way you set GOMAXPROCS.

@denghongcai
Copy link
Author

Thx so much. I found that since Go 1.2, it added pre-emption point to most of function call. If I have to do pure math thing, for example, matrix manipulation, and I want to make it work in a goroutine, runtime.Gosched() is obviously an option, though I also find some performance problems (causing CPU high)...Is using a system level process a best practice?

@dvyukov
Copy link
Member

dvyukov commented Feb 2, 2015

You can insert runtime.Gosched in an outer loop, so that it is called with some reasonable frequency, say every 1ms or so.

@denghongcai
Copy link
Author

It will be the best solution I also think. To avoid some misunderstanding about this problem, a blog post of how it works and the real reason into it is considered to be make. Thx again.

@golang golang locked and limited conversation to collaborators Jun 25, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants