Функция runtime.NumCPU

Функция runtime.NumCPU возвращает количество логических процессоров, доступных текущей Go-программе. Обычно это значение соответствует количеству ядер процессора (включая гиперпоточность), которое операционная система видит для выполнения потоков. Функция не принимает никаких параметров и возвращает целое число типа int.

Синтаксис

goruntime.NumCPU()

Пример с базовым использованием

Давайте получим количество логических процессоров и выведем его на экран:

gopackage main

import (
  "fmt"
  "runtime"
)

func main() {
  cpuCount := runtime.NumCPU()
  fmt.Println(cpuCount)
}

Результат выполнения кода:

go8

В зависимости от аппаратной конфигурации вашего компьютера, вывод может отличаться. Например, на машине с 4-ядерным процессором и гиперпоточностью функция вернет 8.

Пример с параллельными вычислениями

Давайте используем количество процессоров для оптимального распределения задач между воркерами:

gopackage main

import (
  "fmt"
  "runtime"
  "sync"
)

func main() {
  numCPU := runtime.NumCPU()
  fmt.Printf("CPU count: %d\n", numCPU)

  var wg sync.WaitGroup
  chunkSize := 100 / numCPU

  for i := 0; i < numCPU; i++ {
    wg.Add(1)
    go func(workerID int) {
      defer wg.Done()
      start := workerID * chunkSize
      end := start + chunkSize
      fmt.Printf("Worker %d processes range [%d, %d)\n",
        workerID, start, end)
    }(i)
  }
  wg.Wait()
}

Результат выполнения кода:

go"CPU count: 8"
"Worker 0 processes range [0, 12)"
"Worker 1 processes range [12, 24)"
"Worker 2 processes range [24, 36)"
"Worker 3 processes range [36, 48)"
"Worker 4 processes range [48, 60)"
"Worker 5 processes range [60, 72)"
"Worker 6 processes range [72, 84)"
"Worker 7 processes range [84, 96)"

Пример с настройкой GOMAXPROCS

Значение, возвращаемое runtime.NumCPU, часто используется для установки максимального количества параллельных процессов через runtime.GOMAXPROCS:

gopackage main

import (
  "fmt"
  "runtime"
)

func main() {
  numCPU := runtime.NumCPU()
  runtime.GOMAXPROCS(numCPU)
  fmt.Println(runtime.GOMAXPROCS(0))
}

Результат выполнения кода:

go8

Вызов runtime.GOMAXPROCS(0) возвращает текущее значение, не изменяя его. Обычно Go автоматически использует все доступные процессоры, поэтому явный вызов runtime.GOMAXPROCS требуется редко.

Пример с пулом воркеров

Создадим пул воркеров с размером, равным количеству процессоров:

gopackage main

import (
  "fmt"
  "runtime"
  "sync"
)

func main() {
  const tasks = 20
  numWorkers := runtime.NumCPU()
  taskCh := make(chan int, tasks)
  var wg sync.WaitGroup

  for w := 0; w < numWorkers; w++ {
    wg.Add(1)
    go func(workerID int) {
      defer wg.Done()
      for task := range taskCh {
        fmt.Printf("Worker %d processed task %d\n",
          workerID, task)
      }
    }(w)
  }

  for t := 0; t < tasks; t++ {
    taskCh <- t
  }
  close(taskCh)
  wg.Wait()
}

Результат выполнения кода:

go"Worker 0 processed task 0"
"Worker 0 processed task 1"
"Worker 0 processed task 2"
"Worker 1 processed task 3"
"Worker 1 processed task 4"
"Worker 2 processed task 5"
"Worker 2 processed task 6"
"Worker 3 processed task 7"
"Worker 3 processed task 8"
"Worker 4 processed task 9"
"Worker 4 processed task 10"
"Worker 5 processed task 11"
"Worker 5 processed task 12"
"Worker 6 processed task 13"
"Worker 6 processed task 14"
"Worker 7 processed task 15"
"Worker 7 processed task 16"
"Worker 0 processed task 17"
"Worker 1 processed task 18"
"Worker 2 processed task 19"

Количество воркеров соответствует количеству доступных процессоров, что позволяет эффективно утилизировать аппаратные ресурсы системы.

Смотрите также

  • функцию runtime.GOMAXPROCS,
    которая управляет количеством одновременно выполняющихся потоков Go
  • функцию runtime.NumGoroutine,
    которая возвращает количество активных горутин в текущий момент
  • функцию runtime.GC,
    которая запускает сборку мусора
  • функцию runtime.Goexit,
    которая завершает выполнение текущей горутины