Khi chạy lệnh lscpu
trên Linux, nó sẽ liệt kê thông tin CPU trên máy. Lấy một ví dụ có một CPU với 2 nhân và mỗi nhân có hai luồng, điều này cho thấy có 4 nhân khả dụng.
Bây giờ hãy xem chương trình GoLang sẽ xác định bao nhiêu nhân.
Từ đầu ra, NumCPU
và GOMAXPROCS
đều xuất ra 4, điều này là dự kiến. Runtime Go lấy thông tin này như thế nào, nó có lấy thông tin đó thông qua lệnh tương tự như lscpu hoặc /proc/cpuinfo không? Hãy tìm hiểu thêm trong mã nguồn của GoLang.
Trong runtime/debug.go
, nó cho biết giá trị này là từ biến toàn cục ncpu
được đặt khi tiến trình bắt đầu và sẽ không thay đổi sau khi được đặt.
ncpu
được đặt ở đâu? Tìm kiếm từ khóa này bằng grep trong thư mục runtime, trong runtime/os_linux.go
. có một hàm osinit()
gọi getproccount()
để lấy giá trị ncpu.
Bên trong getproccount()
, nó gọi sche_getaffinity()
sẽ có một đầu ra buf
, trong đó mỗi bit có giá trị là 1 sẽ được coi là một nhân.
Hàm sche_getaffinity()
này là một hàm gốc được định nghĩa bằng assembly Go. việc triển khai của nó có thể được tìm thấy trong runtime/sys_linux_amd64.s
.
Từ trên, giá trị của ncpu không giống như đầu ra từ lscpu
, nó là số lượng CPU mà hệ điều hành phân bổ cho tiến trình hiện tại. Trong hầu hết các trường hợp, người ta sẽ thấy ncpu giống với số lượng CPU khả dụng trên hệ điều hành, đó là vì hệ điều hành sẽ cho phép một tiến trình sử dụng tất cả các CPU khả dụng theo mặc định. Nếu muốn giới hạn số lượng CPU được sử dụng bởi một tiến trình, có thể sử dụng cpuset
từ cgroup
để thực hiện thay đổi.
Ví dụ: hãy tạo một cgroup có tên gocpu
.
cgcreate -g cpuset:/gocpu
Nếu muốn chỉ cho phép CPU 0-1 được sử dụng bởi cgroup gocpu, có thể chạy
#echo '0' > cpuset.mems
#echo '0-1' > cpuset.cpus
#echo $$ > tasks
Sau đó, hãy để shell bash chạy trong cgroup mới này và khởi chạy chương trình go một lần nữa, bây giờ nó sẽ chỉ có 2 nhân để sử dụng.