Richard_Synapse wrote: ↑
Sun Nov 07, 2021 11:21 am
[*]If the buffer size is too low, MT should be turned off automatically since the sync overhead becomes too high
I mostly use FLStudio myself which is well-known to sometimes give you very short buffers. What works pretty well there though is using a task-model (each voice is a task) and checking on per-buffer basis whether the buffer length (=nsamples) is very short and if that's the case, compute all the tasks directly, otherwise dispatch to threadpool.
Another thing I'd suggest (and apologies if this is very obvious) is using an atomic counter for task completion: set the counter to the number of tasks before dispatch, have every task decrement (atomically) the counter when finished and then have the last task post() on a semaphore when the counter hits zero after decrement. The main thread can then wait() on that semaphore, just once, and gets woken up only after all the tasks are finished (which is infinitely better than having it sync separately with every task).
That doesn't reduce the sync overhead of actually dispatching tasks though. Something I haven't done (since I just thought of it about 10 minutes ago), but which might be profitable for small buffers is that one could potentially group such tasks into "macro tasks" where you basically combine the processing of multiple voices into a single task such that the total number of voices*samples exceeds some minimum value. This way if we have something like 16 voices and we put the threshold at 32 samples, if the host gives a tiny buffer size of 8, you'll dispatch 32/8 = 4 voices per task, you're still generating 4 tasks for multi-threading, but we don't need to go through the dispatch queue 16 times (where as with longer buffers having separate tasks makes sense to load-balance with multiple threads often processing at different rates).
You could do that with a very simple algorithm too: have each task consist of the "first voice", "number of samples" and "number of voices" and then when generating tasks, loop over the voices, if the nsamples*nvoices of the current task is less than threshold, bump nvoices, otherwise bump task index and when done, dispatch however many tasks you ended up with. If "nsamples" is larger than the threshold, every voice gets it's own task. If the work doesn't divide evenly, the last task will end up with less work (ie. just the "left overs"), but I'd imagine that's not a huge deal.
Preferred pronouns would be "it/it" because according to this country, I'm a piece of human trash.