Skip to content

Instantly share code, notes, and snippets.

@sonicdebris
Last active March 6, 2022 16:28
Show Gist options
  • Save sonicdebris/9bedd785d61f1b595e40b7140ff34580 to your computer and use it in GitHub Desktop.
Save sonicdebris/9bedd785d61f1b595e40b7140ff34580 to your computer and use it in GitHub Desktop.
CPU Isolation notes

Configure htop to show process CPU:

https://unix.stackexchange.com/a/349909

Cpu and affinity in C++ (also advice about lstopo):

https://eli.thegreenplace.net/2016/c11-threads-affinity-and-hyperthreading/#id2

View threads in htop:

http://ask.xmodulo.com/view-threads-process-linux.html

Check isolated cpus:

/sys/devices/system/cpu/isolated

https://unix.stackexchange.com/a/338372

Isolating CPU with isolcpus:

sudo nano /etc/default/grub

add isolcpus=[cpuid] to GRUB_CMDLINE_LINUX_DEFAULT and save, then:

sudo grub-mkconfig -o /boot/grub/grub.cfg

https://www.suse.com/support/kb/doc/?id=7009596 https://wiki.archlinux.org/index.php/kernel_parameters

Isolating CPU, alternative method with cpuset and cgroups:

http://linuxrealtime.org/index.php/Improving_the_Real-Time_Properties#Isolating_CPUs

Isolation and IRQs

Mention of isolcpus also working with IRQ (is it true for antergos/arch?):

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_for_real_time/7/html/tuning_guide/interrupt_and_process_binding

Tuning IRQs:

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-cpu-irq

You can check /proc/interrupts to see whether isolated CPU is used for IRQs or not.

Is there ar IRQ for audio i/o? If yes, how is that affected by isolation? Should we schedule those IRQs on the isolated core? (On its own isolated core if you have more than two cores?)

Antergos doesn't have irqbalance, so it's a matter of setting the affinity for the IRQs to the desired CPUs. there is /proc/irq/default_smp_affinity that should allow setting the affinity of all IRQs (and you can then set the one you want on a single one or a few of them).

https://www.kernel.org/doc/Documentation/IRQ-affinity.txt

I couldn't make it work, but in theory you can also iterate on all IRQs in proc/irq and set the affinity with # echo {hex-mask} > /proc/irq/{num}/smp_affinity. This works, as you can see by cating proc/interrupts.

I noticed that moving the IRQ for the audio device to the CPU hogged by my cpu-hog process doesn't lead to glitches. Which makes sense considering that the IRQs are supposed to always immediately interrupt any other activity in progress on the CPU.

Tried adding a parameter for the sine frequency to be changed from the main thread, both with locks and with atomic load/store. We have issues only when we sleep for ~5 ms in the main thread after taking the lock. Let's see what happens when lowering the priority of the main thread. Setting a lower priority (actually a low-priority scheduler) for the main thread leads to glitches when using the lock with just 1ms of sleep. The glitch is not there if the priority of the main thread is regular. So this is an indication of how priority inversion can be damaging when the scheduler is not friendly to our main thread.

Also, let's see how to isolate CPUs at runtime without having to add a boot param:

  • Unplugging the CPU with echo 0 > /sys/devices/system/cpu/cpu1/online won't work, the CPU will not be available at all
  • With cpuset it may somehow work, but it's complex and not perfect. Isolating a cpu in a cpuset makes it unavailable to a process belonging to another cpuset. So we need to create a cpuset with all the CPUS, run our app on that cpuset and then do some other things to ensure separation of the audio thread from the rest. And, some kernel threads cannot be moved away from the CPU we want to isolate.
  • Apparently the best way is isolcpus boot parameter

CPUSET quick reference

https://stackoverflow.com/questions/11111852/how-to-shield-a-cpu-from-the-linux-scheduler-prevent-it-scheduling-threads-onto

Easiest way to create two sets:

cset shield --cpu 1,3
cset shield --kthread on
cset shield --reset

Pro:

cset set --cpu=0-3 --mem=0 --set=audio
cset proc --move --fromset=root --toset=audio
sudo cset set --cpu=0,2 --mem=0 --set=normal
cset proc --move --fromset=audio --toset=normal
cset set --list
cset proc --kthread --fromset=root --toset=normal
cset proc --kthread --fromset=root --toset=normal --force
@sonicdebris
Copy link
Author

sonicdebris commented Sep 5, 2021

Tried this on my dell laptop (i9 8-cores / 16-threads), on pop_os 20.04:

  • jack (set-up with cadence) using an iRig pro IO, buffer size 64, sr 48khz, 2 buffers
  • kernel: linux 5.11.0 lowlatency
  • isolcpus=12-15 boot option in the lowlatency kernel .conf in /boot/efi/loader/entries
  • verified cpu isolation works with cat /sys/devices/system/cpu/isolated
  • created a cpu set for jack, one for the jack audio realtime thread, and one for pure data
  • moved all jack threads to the jack cpusets, and all pd threads to the pd cpuset
  • cpu load with pd test-audio patch is ~5%
  • getting occasional long bursts of glitching
#get process and threads id-s from htop
sudo cset set --cpu 12,13 for-jack
sudo cset set --cpu 14 for-jack-hiprio
sudo cset proc --move --pid 6203 --toset=for-jack
sudo cset proc --move --pid 6222 --toset=for-jack
sudo cset proc --move --pid 6224 --toset=for-jack
sudo cset proc --move --pid 6223 --toset=for-jack-hiprio
sudo cset set --cpu 15 for-pure-data
sudo cset proc --move --pid 15750 --threads --toset=for-pure-data
# looks like --threads option kind of works but not completely, some purr-data threads where still on non-isolated cpu

@sonicdebris
Copy link
Author

@sonicdebris
Copy link
Author

Threads running on a CPU (eg: 12):
ps -eo psr,command | tr -s " " | grep "^ 12"
The ones in square brackets are kernel threads

@sonicdebris
Copy link
Author

sonicdebris commented Sep 5, 2021

isolcpus docs: https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt
note: nohz breaks isolation on my pop_os install

@sonicdebris
Copy link
Author

Understand which physical core contain which logical processors:
lstopo-no-graphics --no-io --no-legend --of txt and cat /proc/cpuinfo|egrep "processor|core id|physical id"
Turns out that on my dell xps the processors are coupled like: [0,8], [1,9] and so on.
So, for example, to isolate the processors on the last two cores I have to pass 6,14,7,15 to isolcpus

@sonicdebris
Copy link
Author

sonicdebris commented Sep 5, 2021

Set cpu behavior and frequency:
eg: sudo cpupower frequency-set -g performance -d 3.0GHz -u 3.0GHz
Will set governor to performance and frequency fixed around 3GHz. You can check how it works with sudo i7z
echo 0 >> /sys/devices/system/cpu/intel_pstate/no_turbo enables turbo boost ("1" to disable).

Notes:

  • Governor doesn't matter much if you set the same min and max frequency
  • If min and max frequencies are different, performance governor will keep frequencies closer to the max
  • Turbo caps the max frequency, so if you pass -u 3.0GHz to cpupower but turbo is disabled, the max frequency will be 2.4GHz

@sonicdebris
Copy link
Author

sonicdebris commented Sep 5, 2021

Check how many context switches on each cpu over 10 sec:
perf stat -e 'sched:sched_switch' -a -A --timeout 10000
This tip comes from this low latency tuning guide that has some more useful stuff:
https://rigtorp.se/low-latency-guide/

@sonicdebris
Copy link
Author

tips for core partitioning (also for kthreads and irqs):
https://elinux.org/images/0/03/Core-Partitioning-Technique-on-Multicore-Linux-system.pdf

@sonicdebris
Copy link
Author

@sonicdebris
Copy link
Author

sonicdebris commented Sep 6, 2021

Another attempt at deep cpuset. As root:

cset set -s audio-hiprio -c 6                                                               
cset set -s audio-ui -c 7,15
cset set -s system -c 1-5,8-13                                                              
cset proc --move --fromset=root --toset=system                                              
cset proc --kthread --move --fromset=root --toset=system --force                            

Check with: cset set --list

      Name       CPUs-X    MEMs-X Tasks Subs Path
 ------------ ---------- - ------- - ----- ---- ----------
         root       0-15 y       0 y   172    3 /
     audio-ui       7,15 n       0 n     0    0 /audio-ui
 audio-hiprio          6 n       0 n     0    0 /audio-hiprio
       system   1-5,8-13 n       0 n  1306    0 /system

Before this setup, these where the threads on core 6 (audio-hiprio cpuset)

[~] ps -eo psr,command | tr -s " " | grep "^ 6"                                                      
 6 [cpuhp/6]
 6 [idle_inject/6]
 6 [migration/6]
 6 [ksoftirqd/6]
 6 [kworker/6:0H]
 6 [irq/126-PCIe PM]
 6 [irq/157-nvme0q7]
 6 [kworker/6:1-events]
 6 [irq/178-s-iwlwi]
 6 [kworker/6:0]
 6 [kworker/6:2]

After:

[~] ps -eo psr,command | tr -s " " | grep "^ 6"                                                      
 6 [cpuhp/6]
 6 [idle_inject/6]
 6 [migration/6]
 6 [ksoftirqd/6]
 6 [kworker/6:0H]
 6 [irq/126-PCIe PM]
 6 [irq/157-nvme0q7]
 6 [kworker/6:1-events]
 6 [kworker/6:2]

So these seem to have been removed:

 6 [irq/178-s-iwlwi]
 6 [kworker/6:0]

@sonicdebris
Copy link
Author

@sonicdebris
Copy link
Author

sonicdebris commented Jan 19, 2022

@sonicdebris
Copy link
Author

sonicdebris commented Jan 19, 2022

@sonicdebris
Copy link
Author

new realtimeconfigquickscan: https://codeberg.org/rtcqs/rtcqs

@sonicdebris
Copy link
Author

@sonicdebris
Copy link
Author

sonicdebris commented Feb 13, 2022

@sonicdebris
Copy link
Author

compile kernel + xenomai:
https://blog.reds.ch/?p=1308

@sonicdebris
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment