Можете ли вы определить, сколько потоков создаст определенное количество goroutines?

Я понимаю, что goroutines мультиплексируются на несколько потоков ОС, поэтому, если нужно блокировать, например, в ожидании ввода-вывода, другие продолжают работать. Но есть ли способ заранее узнать, сколько потоков я бы породил, если бы я создал n goroutines?

Например, если мы вызываем функцию ниже, мы знаем, сколько системных потоков (или максимального числа) будет создано для n goroutines:

type Vector []float64

// Apply the operation to n elements of v starting at i.
func (v Vector) DoSome(i, n int, u Vector, c chan int) {
    for ; i < n; i++ {
        v[i] += u.Op(v[i])
    }
    c <- 1;    // signal that this piece is done
}

Ответ 1

Согласно Pike Go Course PDF слайды (День 3):

... если вам нужен пользовательский уровень parallelism, вы должны установить $GOMAXPROCS или вызвать runtime.GOMAXPROCS(n). GOMAXPROCS сообщает планировщику времени выполнения, сколько запущенных goroutines, не связанных с syscall, запускается сразу.

Основываясь на этом сообщении в блоге, похоже, что настройка переменной окружения GOMAXPROCS позволяет исправить количество потоков. Я не уверен, как получить число по умолчанию, которое будет выполняться во время выполнения, если вы не укажете это значение.

В этом сообщении в блоге подразумевается, что если вы не установите переменную среды, среда выполнения будет использовать только одно ядро ​​(предположительно, потому что это только используя один процесс.)

Ответ 2

Каждый goroutine может использовать максимум один поток за раз. Использует ли он поток или нет, зависит от того, что он делает. Значение GOMAXPROCS определяет количество потоков, которые могут использоваться при свободном запуске кода Go - другими словами, максимальный уровень parallelism.

Однако можно использовать больше потоков, даже с GOMAXPROCS = 1, когда goroutines блокируются непосредственно на системных вызовах или вызовах на C.

Следующие операции не приводят к тому, что goroutine использует поток при блокировке:

  • операции с каналами
  • сетевые операции
  • спящих
  • все примитивы в пакете sync

Это означает, например, что если у вас много goroutines, которые открывают /dev/ttyxx и блокируют чтение, вы будете использовать поток для каждого из них. То же самое происходит, если вы выполняете нагрузку процессов и ожидаете их выхода.

Ответ 3

В настоящее время gccgo создаст один поток на goroutine.

Я не знаю о 6g.