CPU cores, thread priorities, fast scrolling, xruns

So i have two external displays connected (with displayport-over-USB-type-C). When Ardour is playing back with “follow play head” enabled, it triggered a lot of xruns especially when zoomed in further and it has to scroll faster, i’m guessing because it has to generate more pixels of waveform image at each screen redraw. Previously i had always thought this was a USB bandwidth issue.

What fixes or at least greatly reduces the problem, is to pin Ardour’s threads to different CPU cores, performance cores for DSP/realtime audio threads, and efficiency cores for UI/misc related ones. Performance while Ardour is running is drastically improved, even with the audio interface on the same dock/hub as the two screens.

The CPU in this machine is an Intel Core 7 ultra, it has 6 p-cores, 8 e-cores, and 2 low-power cores. With hyperthreading enabled this gives me 12 threads (virtual CPU’s 0 to 11) on p-cores and virtual cpu’s 12 to 21 on e-cores. With the help of chatgpt i was able to create this little script that can be run any time Ardour is running to pin all the threads to the correct CPU cores:

#!/bin/bash
# Adjust "cpu" and "cpu_gui" to your computer

cpu="0-11"         # should be performance/fast cores
cpu_gui="12-21"    # should be other cores

PID=$(pidof -x ardour-8.12.0)

# Put real-time worker threads with JACK
for T in $(ps -L -p "$PID" -o tid,comm | awk '/^ *[0-9]+ RT(-|)/{print $1}'); do
  taskset -pc "$cpu" "$T"
done

for T in $(ps -L -p "$PID" -o tid,comm | awk '/AudioEngine/{print $1}'); do
  taskset -pc "$cpu" "$T"
done

# Shunt GUI & misc away from RT cores
for T in $(ps -L -p "$PID" -o tid,comm | awk '/ArdourGUI|gmain|Analyzer|DeviceList|PeakFileBuilder|LXVSTEventLoop|TriggerBox/{print $1}'); do
  taskset -pc "$cpu" "$T"
done

# any thread NOT matching RT-* or AudioEngine -> 8-9
ps -L -p "$PID" -o tid=,comm= | awk '!/RT-|AudioEngine/{print $1}' \
  | xargs -r -n1 -I{} taskset -pc "$cpu_gui" {}

I expect this will still be an issue. Since they run off the same IRQ (besides, USB audio interfaces behind a USB hub generally cause trouble and it is a known source of xruns).

Ideally you use different IRQs for the display and the audio interface. That way the graphics driver can be preempted in favor of audio I/O.

as a reference, i made the mistake once of connecting my video camera to the same port as my USB audio interface (at the time, a MOTU 24 channel USB device). The audio interface was unusable if the camera was powered up, even if I was not using the camera. Split them across ports, everything worked as expected …

PS, it should not be needed to pin threads to a given core. The Linux scheduler does an amazing job at that (and also takes P/E and p-hyperthreads into account).

it does however make sense to raise IRQ thread priority of the soundcard.

Boot with threadirqs kernel parameter, then raise the PID of the IRQ corresponding to the USB-soundcard, once it is on a dedicated USB bus with its own IRQ.

see also GitHub - jhernberg/udev-rtirq: Use udev to automatically change the priority of soundcard interrupt handling threads. or autostatic/rtcirqus: rtcirqus, real-time config IRQ udev service, is a Python script that sets the real-time priority of IRQ threads of onboard and USB audio interfaces dynamically. - Codeberg.org (Edit: fixed link)

1 Like

…well, what can i tell you? i get tons of xruns when ardour is scrolling without this trick (audio card on any USB port) and none when using it.

I expect you get better even performance when you separate the soundcard IRQ, and only prioritize that…

@x42 thanks for mentioning rtcqs! But you probably mean rtcirqus: autostatic/rtcirqus: rtcirqus, real-time config IRQ udev service, is a Python script that sets the real-time priority of IRQ threads of onboard and USB audio interfaces dynamically. - Codeberg.org
As far as I know it’s the only tool that kind of works with newer systems that use Message Signaled Interrupts: Message Signaled Interrupts - Wikipedia. Your mileage varies though, especially with crowded USB buses.
Brings up another discussion, how useful is prioritising IRQs on systems that use MSI?

2 Likes

I tried to reproduce this issue but then I only have one external screen that I can connect using a USB-C cable. Not sure if it’s DisplayPort over USB either. It’s pretty crowded on Bus 001 and I see the monitor is there, just as my audio interface. Zero xruns though when I use follow playhead and zoom in.

Bus 001 Device 003: ID 0489:e0d8 Foxconn / Hon Hai Wireless_Device
Bus 001 Device 008: ID 0424:3fb7 Microchip Technology, Inc. (formerly SMSC) Babyface (23596862)
Bus 001 Device 011: ID 0bda:8153 Realtek Semiconductor Corp. RTL8153 Gigabit Ethernet Adapter
Bus 001 Device 012: ID 043e:9a39 LG Electronics USA, Inc. 27UP850 - WK.AEUDCSN - External Monitor 4K
Bus 001 Device 010: ID 05e3:0608 Genesys Logic, Inc. Hub
Bus 001 Device 009: ID 0bda:5411 Realtek Semiconductor Corp. RTS5411 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub