GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing docs.kernel.org — CPU Isolation — The Linux Kernel documentation CPU Isolation¶Introduction¶“CPU Isolation” means leaving a CPU exclusive to a given workload without any undesired code interference from the kernel. Those interferences, commonly pointed out as “noise”, can be triggered by asynchronous events (interrupts, timers, scheduler preemption by workqueues and kthreads, ...) or synchronous events (syscalls and page faults). Such noise usually goes unnoticed. After all, synchronous events are a component of the requested kernel service. And asynchronous events are either sufficiently well-distributed by the scheduler when executed as tasks or reasonably fast when executed as interrupt. The timer interrupt can even execute 1024 times per seconds without a significant and measurable impact most of the time. However some rare and extreme workloads can be quite sensitive to those kinds of noise. This is the case, for example, with high bandwidth network processing that can’t afford losing a single packet or very low latency network processing. Typically those use cases involve DPDK, bypassing the kernel networking stack and performing direct access to the networking device from userspace. In order to run a CPU without or with limited kernel noise, the related housekeeping work needs to be either shut down, migrated or offloaded. Housekeeping¶In the CPU isolation terminology, housekeeping is the work, often asynchronous, that the kernel needs to process in order to maintain all its services. It matches the noises and disturbances enumerated above except when at least one CPU is isolated. Then housekeeping may make use of further coping mechanisms if CPU-tied work must be offloaded. Housekeeping CPUs are the non-isolated CPUs where the kernel noise is moved away from isolated CPUs. The isolation can be implemented in several ways depending on the nature of the noise:
In any case, housekeeping work has to be handled, which is why there must be at least one housekeeping CPU in the system, preferably more if the machine runs a lot of CPUs. For example one per node on NUMA systems. Also CPU isolation often means a tradeoff between noise-free isolated CPUs and added overhead on housekeeping CPUs, sometimes even on isolated CPUs entering the kernel. Isolation features¶Different levels of isolation can be configured in the kernel, each of which has its own drawbacks and tradeoffs. Scheduler domain isolation¶This feature isolates a CPU from the scheduler topology. As a result, the target isn’t part of the load balancing. Tasks won’t migrate either from or to it unless affined explicitly. As a side effect the CPU is also isolated from unbound workqueues and unbound kthreads. Requirements¶
Tradeoffs¶By nature, the system load is overall less distributed since some CPUs are extracted from the global load balancing. Interfaces¶
IRQs isolation¶Isolate the IRQs whenever possible, so that they don’t fire on the target CPUs. Interfaces¶
Full Dynticks (aka nohz_full)¶Full dynticks extends the dynticks idle mode, which stops the tick when the CPU is idle, to CPUs running a single task in userspace. That is, the timer tick is stopped if the environment allows it. Global timer callbacks are also isolated from the nohz_full CPUs. Requirements¶
Constraints¶
Tradeoffs¶In terms of cost, this is the most invasive isolation feature. It is assumed to be used when the workload spends most of its time in userspace and doesn’t rely on the kernel except for preparatory work because:
Checklist¶You have set up each of the above isolation features but you still observe jitters that trash your workload? Make sure to check a few elements before proceeding. Some of these checklist items are similar to those of real-time workloads:
Full isolation example¶In this example, the system has 8 CPUs and the 8th is to be fully isolated. Since CPUs start from 0, the 8th CPU is CPU 7. Kernel parameters¶Set the following kernel boot parameters to disable SMT and setup tick and IRQ isolation:
The full command line is then:
CPUSET configuration (cgroup v2)¶Assuming cgroup v2 is mounted to /sys/fs/cgroup, the following script isolates CPU 7 from scheduler domains. cd /sys/fs/cgroup # Activate the cpuset subsystem echo +cpuset > cgroup.subtree_control # Create partition to be isolated mkdir test cd test echo +cpuset > cgroup.subtree_control # Isolate CPU 7 echo 7 > cpuset.cpus echo "isolated" > cpuset.cpus.partition The userspace workload¶Fake a pure userspace workload, the program below runs a dummy userspace loop on the isolated CPU 7. #include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int main(void)
{
// Move the current task to the isolated cpuset (bind to CPU 7)
int fd = open("/sys/fs/cgroup/test/cgroup.procs", O_WRONLY);
if (fd < 0) {
perror("Can't open cpuset file...\n");
return 0;
}
write(fd, "0\n", 2);
close(fd);
// Run an endless dummy loop until the launcher kills us
while (1)
;
return 0;
}
Build it and save for later step: # gcc user_loop.c -o user_loop The launcher¶The below launcher runs the above program for 10 seconds and traces the noise resulting from preempting tasks and IRQs. TRACING=/sys/kernel/tracing/ # Make sure tracing is off for now echo 0 > $TRACING/tracing_on # Flush previous traces echo > $TRACING/trace # Record disturbance from other tasks echo 1 > $TRACING/events/sched/sched_switch/enable # Record disturbance from interrupts echo 1 > $TRACING/events/irq_vectors/enable # Now we can start tracing echo 1 > $TRACING/tracing_on # Run the dummy user_loop for 10 seconds on CPU 7 ./user_loop & USER_LOOP_PID=$! sleep 10 kill $USER_LOOP_PID # Disable tracing and save traces from CPU 7 in a file echo 0 > $TRACING/tracing_on cat $TRACING/per_cpu/cpu7/trace > trace.7 If no specific problem arose, the output of trace.7 should look like the following: <idle>-0 [007] d..2. 1980.976624: sched_switch: prev_comm=swapper/7 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=user_loop next_pid=1553 next_prio=120 user_loop-1553 [007] d.h.. 1990.946593: reschedule_entry: vector=253 user_loop-1553 [007] d.h.. 1990.946593: reschedule_exit: vector=253 That is, no specific noise triggered between the first trace and the second during 10 seconds when user_loop was running. Debugging¶Of course things are never so easy, especially on this matter. Chances are that actual noise will be observed in the aforementioned trace.7 file. The best way to investigate further is to enable finer grained tracepoints such as those of subsystems producing asynchronous events: workqueue, timer, irq_vector, etc... It also can be interesting to enable the tick_stop event to diagnose why the tick is retained when that happens. Some tools may also be useful for higher level analysis:
|
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |