isolcpus và cô lập scheduler domain¶
Cô lập CPU (CPU isolation) là dành riêng một số core cho một workload, sao cho kernel không chen công việc của nó vào các core đó. Trang này trình bày tham số boot isolcpus= và cách thay thế nó bằng cpuset của cgroup v2, theo thứ tự: khái niệm housekeeping, cú pháp và các cờ của isolcpus=, cách kernel xử lý tham số, cpuset isolated partition, cách kiểm tra và các giới hạn. Phần tắt tick định kỳ được trình bày ở nohz_full và adaptive tick, phần định tuyến ngắt ở IRQ affinity và irqbalance.
Nội dung dựa trên tài liệu và mã nguồn kernel mainline bản 7.4-rc1. Các mốc phiên bản được ghi rõ ở từng chỗ.
Nhiễu kernel và housekeeping¶
Tài liệu kernel gọi các can thiệp của kernel lên một core là nhiễu (noise). Nhiễu có hai loại: bất đồng bộ, như ngắt, timer, workqueue và kthread chiếm core; và đồng bộ, như system call và page fault do chính workload gây ra. Với đa số workload, nhiễu này không đáng kể. Với xử lý gói tin băng thông cao bằng DPDK, xử lý tín hiệu vRAN hoặc vòng điều khiển real-time, mỗi lần bị chen ngang làm tăng độ trễ tối đa (worst-case latency).
Housekeeping là phần việc nền mà kernel phải làm để duy trì dịch vụ của nó. Core housekeeping là các core không bị cô lập, nơi nhận phần việc đó. Cách đẩy việc ra khỏi core cô lập phụ thuộc vào tính chất của việc:
| Loại việc | Ví dụ | Cách xử lý |
|---|---|---|
| Không gắn với core nào (unbound) | Unbound workqueue, kthread, timer toàn cục | Chuyển sang core housekeeping |
| Gắn với một core (bound), có bản thay thế | RCU callback | Chuyển sang cơ chế có khóa, chạy ở kthread riêng (rcu_nocbs) |
| Gắn với một core, không có bản thay thế | Lockup watchdog, clocksource không ổn định | Tắt tính năng, coi là không tương thích với core cô lập |
| Gắn với một core, có cơ chế bù | Tick định kỳ | Tắt tick khi core chỉ chạy một task (nohz_full), đổi lại chi phí vào/ra kernel cao hơn |
Do việc housekeeping luôn tồn tại, hệ thống phải giữ ít nhất một core housekeeping. Tài liệu kernel khuyến nghị nhiều hơn trên máy nhiều core, ví dụ mỗi NUMA node một core.
Cú pháp isolcpus¶
<cpu-list> dùng cú pháp danh sách CPU chung của kernel command line (ví dụ 2-7 hoặc 1,3-5), đánh số từ 0. Xem cách truyền tham số qua bootloader ở Kernel Command Line.
| Cờ | Tác dụng | Tương đương |
|---|---|---|
domain |
Bỏ core khỏi thuật toán cân bằng tải và lập lịch SMP. Task không tự di chuyển tới hoặc rời khỏi core, trừ khi được gắn affinity tường minh. Core cũng bị loại khỏi unbound workqueue và unbound kthread | Cpuset partition isolated |
nohz |
Tắt tick khi core chỉ chạy một task, đồng thời offload RCU callback | nohz_full= |
managed_irq |
Tránh gửi managed interrupt (ngắt do kernel tự quản lý affinity) tới core cô lập, theo kiểu best effort | Không có |
Hình dưới so sánh cân bằng tải trước và sau khi cô lập bằng cờ domain: core cô lập nằm ngoài scheduler domain, scheduler chỉ di chuyển task giữa các core housekeeping.
Khi không ghi cờ nào, kernel dùng mặc định domain. Vì vậy isolcpus=2-7 và isolcpus=domain,2-7 cho cùng kết quả. Có thể kết hợp nhiều cờ, ví dụ isolcpus=domain,managed_irq,2-7.
Cờ managed_irq chỉ có hiệu lực khi mask ngắt mà kernel tự gán cho một hàng đợi thiết bị chứa cả core cô lập lẫn core housekeeping. Khi đó ngắt được hướng sang core housekeeping. Nếu mask của hàng đợi chỉ gồm core cô lập, cờ này không thay đổi việc định tuyến, nhưng ngắt của hàng đợi đó chỉ phát sinh khi chính task trên core cô lập gửi I/O. Chi tiết về managed interrupt nằm ở IRQ affinity và irqbalance.
Xử lý tham số trong kernel¶
Hai tham số isolcpus= và nohz_full= cùng được xử lý trong kernel/sched/isolation.c. Mỗi tham số được chuyển thành một cpumask housekeeping (tập core không bị cô lập) cho từng loại việc:
| Kiểu housekeeping | Bật bởi | Ý nghĩa |
|---|---|---|
HK_TYPE_DOMAIN |
isolcpus=domain (hoặc không cờ), cpuset isolated |
Core tham gia scheduler domain và unbound workqueue |
HK_TYPE_MANAGED_IRQ |
isolcpus=managed_irq |
Core được ưu tiên nhận managed interrupt |
HK_TYPE_KERNEL_NOISE |
nohz_full= hoặc isolcpus=nohz |
Core nhận tick, timer, RCU callback và các nhiễu khác thay cho core nohz_full |
Các subsystem khác gọi housekeeping_cpumask() để biết nên đặt công việc ở đâu. Khi kết hợp tham số, kernel kiểm tra một số ràng buộc và in cảnh báo vào log boot nếu vi phạm:
- Nếu cả
nohz_full=vàisolcpus=nohzcùng được dùng, hai danh sách phải giống nhau. Nếu khác, kernel inHousekeeping: nohz_full= must match isolcpus=và bỏ tham số thứ hai. - Phải còn ít nhất một core có mặt (present) không thuộc
nohz_full=lẫnisolcpus=domain. Nếu không, kernel bỏ qua tham số và in cảnh báo. - Cờ không hợp lệ (chứa ký tự không phải chữ cái hoặc
_) làm cả tham số bị bỏ. Cờ chỉ gồm chữ cái nhưng không biết thì bị bỏ qua với thông báoisolcpus: Skipped unknown flag.
Vì vậy, sau khi đổi tham số, cần đọc dmesg | grep -i -E "housekeeping|isolcpus" để chắc chắn tham số được nhận.
Cpuset isolated partition¶
Cpuset trong cgroup v2 cung cấp cùng hiệu ứng với isolcpus=domain nhưng thay đổi được lúc chạy. Một cgroup có thể được đặt thành partition root qua file cpuset.cpus.partition:
| Giá trị | Ý nghĩa |
|---|---|
member |
Thành viên bình thường của partition cha (mặc định) |
root |
Partition root, tạo một scheduler domain riêng gồm các core độc quyền của nó |
isolated |
Partition root không có cân bằng tải, các core bị loại khỏi unbound workqueue |
Partition giữ quyền dùng độc quyền tập core của nó: cgroup bên ngoài partition không dùng được các core đó. Khi đọc lại, file có thể hiện root invalid (<lý do>) hoặc isolated invalid (<lý do>) nếu điều kiện hợp lệ bị phá, ví dụ do hotplug CPU hoặc do sửa cpuset.cpus. File này hỗ trợ poll và inotify để một agent ở user space theo dõi thay đổi trạng thái.
File cpuset.cpus.isolated ở cgroup gốc (chỉ đọc) liệt kê mọi core đang bị cô lập, gồm core của các isolated partition và core cô lập lúc boot bằng isolcpus=domain. Core cô lập lúc boot vẫn được liệt kê kể cả khi partition dùng chúng đã bị hủy.
Hình dưới là cây cgroup sau khi chạy ví dụ bên dưới: partition rt/ giữ riêng CPU 7, các cgroup khác chỉ còn CPU 0-6.
Ví dụ cô lập CPU 7 trên máy 8 core, giả sử cgroup v2 được mount ở /sys/fs/cgroup (theo ví dụ trong tài liệu CPU isolation của kernel):
cd /sys/fs/cgroup
echo +cpuset > cgroup.subtree_control
mkdir rt
echo 7 > rt/cpuset.cpus
echo isolated > rt/cpuset.cpus.partition
cat rt/cpuset.cpus.partition # kỳ vọng: isolated
echo $$ > rt/cgroup.procs # đưa shell hiện tại vào partition
Những điểm cần lưu ý khi dùng cpuset:
- Nếu partition có nhiều core, task trong đó cần được gắn affinity tới từng core cụ thể. Không có cân bằng tải nên scheduler không tự phân bố task.
- Core đã cô lập bằng
isolcpus=lúc boot chỉ được đưa vào partition kiểuisolated, không đưa vào partitionroot. - Không thể tạo partition con kiểu
rootbên dưới partition cha kiểuisolated.
Todo
Chưa kiểm chứng cách cpuset partition tương tác với cây cgroup do systemd quản lý (thuộc tính AllowedCPUs= của unit). Cần thử trên hệ thống thực trước khi dùng cách ghi trực tiếp vào /sys/fs/cgroup ở môi trường production.
Giá trị isolated của cpuset.cpus.partition có trong tài liệu cgroup v2 từ kernel 6.1. File cpuset.cpus.isolated có từ kernel 6.8.
Trạng thái deprecated¶
Trong kernel-parameters.txt, isolcpus= mang nhãn [Deprecated - use cpusets instead] tới hết kernel 7.1. Từ kernel 7.2, nhãn này bị bỏ. Tài liệu mới Documentation/admin-guide/cpu-isolation.rst (có từ kernel 7.1) xếp hai cách như sau:
- Cpuset isolated partition là cách được khuyến nghị, do điều chỉnh được lúc chạy.
isolcpus=domainlà phương án kém linh hoạt hơn: cô lập lúc boot là không đảo ngược được, không thể đưa core trở lại scheduler domain mà không reboot.
Cờ managed_irq và nohz không có bản tương đương trong cpuset, nên vẫn phải dùng tham số boot cho hai phần này.
So sánh các cách gắn task vào core¶
| Cách | Phạm vi | Thay đổi lúc chạy | Ngăn task khác chạy trên core | Bỏ cân bằng tải |
|---|---|---|---|---|
taskset, sched_setaffinity() |
Một task | Có | Không | Không |
Cpuset member |
Một nhóm task | Có | Không | Không |
Cpuset partition root |
Một nhóm task, core độc quyền | Có | Có, với cgroup ngoài partition | Không, có domain riêng |
Cpuset partition isolated |
Một nhóm task, core độc quyền | Có | Có, với cgroup ngoài partition | Có |
isolcpus=domain |
Toàn hệ thống | Không | Chỉ ngăn scheduler tự đưa task tới. Task gắn affinity tường minh vẫn chạy được | Có |
taskset chỉ giới hạn nơi một task được chạy, không ngăn task khác chạy trên cùng core. Do đó taskset thường dùng kết hợp với một trong hai cơ chế cô lập ở cuối bảng.
Kiểm tra cấu hình¶
cat /proc/cmdline # tham số boot đang dùng
cat /sys/devices/system/cpu/isolated # core cô lập bằng isolcpus= (domain)
cat /sys/devices/system/cpu/housekeeping # core housekeeping (kernel 6.19 trở lên)
cat /sys/fs/cgroup/cpuset.cpus.isolated # core cô lập lúc boot và trong partition
cat /sys/devices/virtual/workqueue/cpumask # core được chạy unbound workqueue
ps -eLo psr,pid,comm | awk '$1>=2' # thread đang chạy trên core 2 trở lên
File /sys/devices/system/cpu/housekeeping chỉ có giá trị khi dùng isolcpus=nohz hoặc nohz_full=. Kernel thread per-CPU (ví dụ ksoftirqd/N, kworker/N:M, migration/N, cpuhp/N) vẫn tồn tại trên core cô lập. Đây là bình thường: chúng gắn với core theo thiết kế và chỉ gây nhiễu khi có việc. Tài liệu kernel-per-CPU-kthreads.rst liệt kê từng loại và cách giảm nhiễu của chúng.
Để đo nhiễu thực tế, dùng rtla osnoise hoặc ftrace với event sched_switch và irq_vectors trên core cô lập. Quy trình đo được trình bày ở nohz_full và adaptive tick.
Giới hạn và lưu ý¶
isolcpus=domainkhông ngăn ngắt thiết bị tới core cô lập. Cần thêmirqaffinity=, chỉnhsmp_affinityvà cờmanaged_irq.isolcpus=domainkhông tắt tick. Tick định kỳ vẫn chạy trên core cô lập cho tới khi dùngnohz_full=.- Core cô lập không có cân bằng tải. Nếu gắn hai task vào cùng một core cô lập trong khi core cô lập khác rảnh, scheduler không chuyển task sang core rảnh.
- Kernel thread unbound được đưa ra khỏi core cô lập, nhưng phần mềm user space vẫn có thể tự gắn affinity vào core cô lập. Cần kiểm tra lại affinity của các daemon sau khi cấu hình.
- Cô lập core không thay thế cho các cấu hình khác: khóa bộ nhớ bằng
mlock(), tắt SMT, giới hạn C-state sâu, cố định tần số và kiểm tra System Management Interrupt (SMI) của firmware. Tài liệu CPU isolation của kernel liệt kê các mục này trong phần checklist.
Liên quan¶
- nohz_full và adaptive tick: tắt tick định kỳ trên core cô lập.
- IRQ affinity và irqbalance: đẩy ngắt thiết bị ra khỏi core cô lập.
- Real-time KVM tuning (Virtualization): áp dụng cô lập core cho host và guest khi chạy VM real-time.
- DPDK (Embedded): workload poll-mode thường chạy trên core cô lập.
- Kernel Command Line: cách truyền tham số boot.
Tài liệu tham khảo¶
- Kernel docs: CPU Isolation (
Documentation/admin-guide/cpu-isolation.rst) - Kernel docs: kernel-parameters, mục
isolcpus= - Kernel docs: Control Group v2, mục Cpuset
- Kernel docs: Reducing OS jitter due to per-cpu kthreads
- Mã nguồn
kernel/sched/isolation.c - ABI:
/sys/devices/system/cpu/isolated,nohz_full,housekeeping - Các mốc phiên bản (nhãn deprecated, file
cpu-isolation.rst,cpuset.cpus.isolated,/sys/devices/system/cpu/housekeeping) được xác định bằng cách so sánh tài liệu trong các tagv6.0tớiv7.3của cây mã nguồn Linux.