FR: Thread-Priority vs Efficiency/Performance Cores

Ok, how do you get a thread running on P-core in the first place?

I think the point is you don’t. As I understand it you create a thread and let the OS know how high priority it is, and certain boundaries that you promise not to break (with JUCE you achieve this by calling startRealtimeThread() and supplying the RealtimeThreadOptions to specify the boundaries). Then based on that, other competing priorities, and how well behaved the code in your thread is, the OS decides if it will be placed on a P-core or E-core as well as when to wake the thread. If you additionally join an audio workgroup I suspect it will help the scheduler to decide when to wake your thread to complete any work.

To be clear I can’t say the above with any real authority but that’s how I understand it works.

In experiments I did with the HighResolutionTimer I found when the thread was upgraded to a realtime thread the performance was exceptional and it was very hard to downgrade the performance which suggests to me that not only was it running on a P-core but actually even when I pushed it well outside the boundaries I specified for the thread it remained on one without any noticeable penalty. However, your experience may differ.

2 Likes

Briefly scanning the code changes, at first glance this looks great - I may not get time to try until later in September though.

I don’t see a mechanism/code changes for VST3 and Standalone builds support though (Standalone is definitely possible - I did it with changes in a custom version of juce_StandaloneFilterWindow.h (7.0.3) - VST3 maybe requires support from Steinberg to add something like the RenderContextObserver event? as seen in the au_1 code) - is it the case this code update currently only supports AU/AUV3?

It supports AU, AUv3 (client and hosted), and Standalone.

No VST3 support, I don’t think it’s part of the spec?

It should be noted, that AUv3 Workgroups don’t work, it looks like an Apple bug.

Would this mean that juce::Thread is no longer a “pure” wrapper to native OS threads?
If it now has plugin-format dependent features?

Please correct me if I am wrong (I hope I am )

I do see the macOS / iOS “disclaimers”, but nothing about AU/AUv2 in the documentation on develop

Great to know standalone is also supported - I need to look more carefully in the code to understand how that works.
I feel it’s a bit strange that Steinberg didn’t already update their spec/API to support Apple’s audio workgroups though… it’s been around for quite some time now - and the multi-threaded performance difference when not used is quite drastic on some M silicon devices… so I have to tell customers to avoid the VST3 version of my plugin on Mac silicon.

juce::Thread has no specialisation for Workgroups.

2 Likes

Thank you for correcting me.

I do find it confusing that these long time discussions about RT threads on MacOS have apparently been addressed in the code for a specific plugin format, while I (and maybe others) have interpreted this as MacOS thread API stuff.

Don’t worry. Everyone (including us) is playing catch-up when it comes to Apple’s new threading architecture!

Ah! Well, technically it is threading-related (Workgroups aren’t restricted to audio), but we only use them in an audio context. You have to explicitly opt into them and don’t effect normal threading use.

1 Like

I think the confusion arrises from the fact that you can’t or at least shouldn’t join a workgroup unless you’re on a realtime thread.

So you can create a realtime thread independently from creating/joining a workgroup, but you can’t/shouldn’t join a workgroup unless you’re on a realtime thread.

Then as I understand it there are some cases where you can join a preexisting work group, say from a CoreAudio device or in the AU / AUv3 formats.

I hope that makes sense.

1 Like

Thank you Anthony

@oli1 Is it OK for for a Thread attached to an AudioWorkgroup to call wait() when it has no work to do?

@getdunne to the best of my knowledge this should be fine (might depend on the wait implementation in some cases), after all your thread has to indicate to the scheduler that it’s not doing anything at some point. This is exactly what the HighResolutionTimer does.

1 Like

And does the ms in wait really matter? If not, what ms value are we supposed to pass? In small block sizes a millisecond might not even cut it.

It would be great if that would be included in the example above @oli1, since “do you work” always includes being finished before the deadline periodically.

EDIT: having done my research in advance (of course :man_facepalming:) I found this article by apple: Adding Parallel Real-Time Threads to Audio Workgroups | Apple Developer Documentation
But that kind of opens the same questions that it answers, at least for me not knowing what they mean by semaphores or how to use the c++ classes properly in this context.

You should be able to do sub ms waits now if you need to.

But how am I supposed to know how much time is left between now and the next cycle. I can’t think of any way to get the information of how much time elapsed by not also making a system call.

I think I imagined in many cases something else would wake the thread up when work needs to be carried out.

Also I think because there has to be some synchronisation here I’m assuming it’s basically impossible to avoid system calls. I would suggest for the DSP part continue to follow normal rules but you can wait and signal around the DSP call to manage the synchronisation required to get the calls occurring at the expected intervals. If you really want to just run at some known interval and there is no other synchronisation that needs to occur maybe a HighResolutionTimer would work well for your use case?

No, I’m for sure talking about aux real-time threads here. I’m just trying to figure out, if calling wait(-1) is gonna be the correct way to let MacOS know I’m done for this cycle or if thats gonna demote me to an E-Core for improper behaviour :sweat_smile:

(Thanks for trying to explain it!!)

I suspect it’s fine to call wait (-1) to be honest but it’s always hard to say these things with any real sense of authority. I can’t see how the semaphore example from Apple is really any different if the semaphore is never incremented their thread won’t wake :person_shrugging:

1 Like