เมื่อเรียกใช้คำสั่ง lscpu
บน Linux มันจะแสดงรายการข้อมูล CPU บนเครื่อง ยกตัวอย่างเช่น มี CPU หนึ่งตัวที่มี 2 คอร์ และแต่ละคอร์มีสองเธรด ซึ่งหมายความว่ามี 4 คอร์ที่พร้อมใช้งาน
ตอนนี้มาดูกันว่าโปรแกรม GoLang จะระบุจำนวนคอร์ได้เท่าไหร่
จากผลลัพธ์ NumCPU
และ GOMAXPROCS
ทั้งคู่แสดงผล 4 ซึ่งเป็นไปตามที่คาดไว้ Go runtime ได้ข้อมูลนี้มาอย่างไร มันได้มาจากคำสั่งที่คล้ายกับ lscpu หรือ /proc/cpuinfo หรือไม่? มาลองดูใน source code ของ GoLang กัน
ใน runtime/debug.go
มันบอกว่าค่านี้มาจากตัวแปร global ncpu
ซึ่งถูกตั้งค่าเมื่อกระบวนการเริ่มต้นและจะไม่เปลี่ยนแปลงหลังจากตั้งค่าแล้ว
ncpu
ถูกตั้งค่าที่ไหน? ค้นหาคำค้นหานี้ด้วย grep ในไดเร็กทอรี runtime ใน runtime/os_linux.go
มีฟังก์ชัน osinit()
ซึ่งเรียก getproccount()
เพื่อรับค่า ncpu
ภายใน getproccount()
มันเรียก sche_getaffinity()
ซึ่งจะมีผลลัพธ์ buf
โดยแต่ละบิตที่มีค่าเป็น 1 จะถือว่าเป็นหนึ่งคอร์
ฟังก์ชัน sche_getaffinity()
เป็นฟังก์ชันเนทีฟที่กำหนดด้วย go assembly การใช้งานสามารถพบได้ใน runtime/sys_linux_amd64.s
จากข้างต้น ค่าของ ncpu ไม่เหมือนกับผลลัพธ์จาก lscpu
มันคือจำนวน CPU ที่ OS จัดสรรให้กับกระบวนการปัจจุบัน ในกรณีส่วนใหญ่ คุณจะเห็นว่า ncpu เหมือนกับจำนวน CPU ที่มีอยู่ใน OS นั่นเป็นเพราะ OS จะอนุญาตให้กระบวนการหนึ่งใช้ CPU ทั้งหมดที่มีอยู่ได้โดยค่าเริ่มต้น ถ้าต้องการจำกัดจำนวน CPU ที่จะใช้โดยกระบวนการหนึ่ง สามารถใช้ cpuset
จาก cgroup
เพื่อทำการเปลี่ยนแปลง
ตัวอย่างเช่น มาสร้าง cgroup ชื่อ gocpu
กัน
cgcreate -g cpuset:/gocpu
ถ้าต้องการอนุญาตให้ใช้เฉพาะ CPU 0-1 โดย cgroup gocpu สามารถเรียกใช้
#echo '0' > cpuset.mems
#echo '0-1' > cpuset.cpus
#echo $$ > tasks
จากนั้นให้เชลล์ bash เรียกใช้ใน cgroup ใหม่นี้ และเรียกใช้โปรแกรม go อีกครั้ง ตอนนี้มันจะมีเพียง 2 คอร์ที่จะใช้