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.
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