4 ms·
I read the link. I think your assumptions are wrong and definitely don't match my use case. I know there is a cost of context switching, but even with adding al
by varispeed 6y ago
I read the link. I think your assumptions are wrong and definitely don't match my use case. I know there is a cost of context switching, but even with adding all that I was getting much better performance. I work with 1024 buffer and use CPU heavy plugins. Let's say that my CPU (i9 9900k @5GHz) can run 8 plugins maximum on one core. Now I have 4 tracks, and each track has 4 plugins. That sounds okay, but as soon as I use a send effect on three tracks, they are being processed in one thread and that expects one core to serve 12+1 plugins. Suddenly I get overload and I can't play anything. If I use jBridge, the plugins on each track will run in parallel utilising all cores and playback is smooth. The cpu usage per plugin is higher because of the overhead of the wrapper, but I am able to much more plugins without breaking up.
I think Ableton model does not take into account that you are bound by how many plugins one core can service and if you try to cram as many plugins into one thread you'll have performance issue. The strategy should be the opposite - trying to spread the load onto as many cores as possible.
- PaulDavisThe1st 6y agoIf plugins A, B and C are present in a given signal path, and ordered [ A, B, C ], then you cannot parallelize their execution. A must run first, then its output is fed to B, which must run to completion, and its output is fed to C. Using a single thread for this is the only sane implementation. If you have plugins A, B and C spread across 3 signal paths, then you can certainly run them on different cores, which Ableton (and Ardour and almost any other DAW at this point) will do, by virtue on running each signal path in its own thread. The signal path/thread containing plugin A will execute on a thread/core, independently of the one containing B or the one containing C.
- varispeed 6y agoLet me try to explain again. In Ableton one signal path executes in one thread. Any track that goes to send or to a group gets added to one thread, so that if you have [A, B, C] on track one and [D, E, F] on track two - they will run in parallel - that's fine. However, if you send track one and track two to a send track with [G], they both run on a single thread, so it becomes [A, B, C, D, E, F, G], if a single core can only process four plugins, Ableton will be stalling. If you run each plugin in a separate process, then [A, B, C] and [D, E, F] will run in parallel and the results will go to [G]. As long as either [A, B, C] or [D, E, F] will not exhaust the single core, the playback will be smooth. The same happens if you group tracks or use side chain. Plugins in the chain will all run on single thread, but they could run in parallel up until the point where they "meet". Simplest way to achieve that is to do that sandboxing or more efficient way would be to improve the thread allocation to be more granular.
- PaulDavisThe1st 6y agoThe specific example you cite seems to be: [ A, B, C ] --+ | +--> [ G ] | [ D, E, F ] --+ If Live really insists on running [ A, B, C, D, E, F, G ] all in a single thread, then I agree with you, Live is being sub-optimal at best, dumb at worst. Despite their description supporting this notion that their scheduling works this way, I'm skeptical, because they're just not that dumb (I hope! :) However, sandboxing is absolutely not the simplest way to fix this. Ardour does not and will never sandbox plugins in processes. It just uses a topological sort and a dataflow algorithm to decide what can be run and when, and would execute [ A, B, C ] and [ D, E, F ] in parallel (or could, if on appropriate hardware), before finally running [ G ]. Moving plugins into a separate process has both overhead and complications, and is basically a crazy way to fix this issue, if indeed it is an issue as described.
- varispeed 6y agoYes this is what's happening in Ableton and by your description I'd love if Ableton did the same thing as Ardour. I understand sandbox is not the simplest, but it is exactly what jBridge does and it gives me better performance in Ableton, so by simplest I meant that Ableton wouldn't have to change how they do processing, as jBridge is just a wrapper - does not modify Ableton in any way.
- spacechild1 6y agoAgain, sandboxing is not done for performance reasons. On the contrary, it degrades performance because of the context switch and thread synchronization overhead. I am saying this as someone who has developed a VST plugin host with sandboxing options. Finally, please make sure you understand what Paul Davis has tried to explain you. He's a well-respected industry expert.
- spacechild1 6y agoTo elaborate why sandboxing itself can't help performance, let's assume you have an FX chain A -> B -> C and "B" is sandboxed. After you've computed "A", you take the output and pass it to "B". You then have to wait for "B" to finish before you can go on and compute "C". So while the subprocess for "B" might run in another thread, the main audio thread has to go to sleep. See how there's actually no parallelism at play? In fact, you lose performance because context switches and thread synchronization (especially wake up from sleep) takes time. I think jBridge might actually collect the result of the subprocess in the next DSP tick. This means that the thread can go on to compute "C" because it can take the result of "B" from the previous DSP tick. Now you indeed have things run in parallel. However, this adds additional latency of 1 audio block. If you have several of such sandboxed plugins in a row, this can easily add up. This is technique is sometimes called the "pipelining" (see "2.3" in https://www.complang.tuwien.ac.at/Diplomarbeiten/blechmann11.pdf https://www.complang.tuwien.ac.at/Diplomarbeiten/blechmann11...). Note that you don't need sandboxing for this. You can just as well dispatch items to a thread pool, so everything stays within the same process. So I think the speed up you observe with jBridge has nothing to do with sandboxing per-se, but is just a side effect of its implementation. I can't prove this because I can't look at the source code, but for me this is the most likely explanation.