Feature request: expanding the scope of parallel processing
Dear Uncle ’74,
I really appreciate the option of parallel audio processing which appeared in Max 6 because it allows one to better use his computer processing power, especially with current machines having now four cores or more.
However patchers must be completely independant to benefit from this option. One then has to open several windows to run his setup and each patch has to be saved separately. Moreover, there is a risk to remove an important window from memory rather than just close it as it would happen with a regular subpatcher. Also, when using independant patchers, one cannot organize them in tabs (another highly useful Max 6 feature).
So my request is: please allow regular subpatchers to be processed in parallel with the main patcher like independant patchers (even if this prevents audio inputs and outputs from the main patch). By the way, expanding parallel processing to non-audio patchers would be nice too.
Thank you for considering these requests.
From my understanding (I’ve only done this once, but with relatively good results), you could simply make a [poly~] with only one instance, and parallel processing set to 1 (eg [poly~ thepatch 1 @parallel 1]). This will make the poly~ patch start it’s own thread, though poly~ can be a bit finicky at times, this gives you some other features as well (such as upsampling that chunk of your patch, smaller vector sizes for that segment, etc). My experience doing things this way was not audio-related (I was doing some jitter stuff, inside a poly~… maybe some audio analysis in there too I don’t really remember), so I’m not sure if this could cause mis-match problems when you jump back out to your ‘main’ patch.
Anyway, just a thought.
+1 on that particularly since 4+ cores is becoming standard.
@ MuShoo : hi, I’d be curious to see an exemple of what you describe, I’m not sure this could work since the poly~ reference for the parallel attribute says that parallel processing will only work for dispatching mutliple voices of one poly~ instance :
"Note : At this time, you cannot specify a single subpatcher on a different core. When enabled, this attribute splits up the number of voices between the number of processors available. It is primarily intended for patches that use a significant amount of CPU within multiple voices of the same poly~ object, and the multithreading overhead is primarily useful for larger signal vector sizes (at least 32 or greater). Other situations will not benefit. Using the default threadcount (which is equal to the number of physical cores) is best."
Am I missing your point?
I’m pretty sure (from a conversation with Joshua Kit Clayton on this forum, some years ago) that the first voice of a poly~ @parallel 1 runs in the regular audio thread. So no, poly~ won’t help you with this scenario.
On the other hand, a subset of Alex Harker’s objects ( http://alexanderjharker.co.uk/Software.html ) is designed to address your need.
As a final note, I really wish more flexible parallel processing in the message world… kind of an official, supported and non-crash-prone version of CNMAT’s thread.fork/thread.join ( http://cnmat.berkeley.edu/downloads )…
Andrea is right, with poly~ with parallel set to 1, the first instance of the poly~ is always in the main audio thread. Tabs is great and everything, but having multiple top level patches is the best approach in Max 6. Not only for DSP, but also for the control, each top level patcher has its own scheduler.
Actually, this multi-scheduler thing somehow puzzles me. I have these two top-level patches:
----------begin_max5_patcher---------- 432.3ocuTEsaBBCE8Y3qnoOyLkh.l819NVLlJbE6FzRZqN2L9uOZAbpaNQiw Gnkd3168bNba256gmK2.ZL5YzqHOus9ddNHKfW2ZObEaSVIS6BCWAZMq.vAs ey.aLN7DROzBovn4eAV3P5HRGLO2Emb9aOk1GZMyjsjKJlofLSKKnoM6.kFY GinihCPgSFQPS61gXUEWTBFGYnGTQAqxUQ7KJNqD+S3xUl93C6PagLeVCs0D iQSseYmuucHXfVg.9nQM+xIpXuCBoAPgDh8Y39R7E8klz4lBcSTx4blnqzYn myYVTJYFbP+K2Sex5QM0a31y3KaOzD6Tb380cH2wlCvnjn3qoqH5hxdbrcLI 9+U8c6zxbln315DLxhhx82cbfFoW9W6jd0chFqYpFwX.0LPvlW5HI4uze30o Rt3j1cWEwkbwoWX53rE+XkqkqTY8Yq63MJbOuyAsgKXFtTbPLiOJlk77bPbn hx4ZqHyOea40vFx.XC4gvlzAvl3GFahF.aReXrgN.1DcirosolUWuFT5tT5H RyA22jJ6xj.2RtncoKiXErl2G+Dea114+Mvuad9Q -----------end_max5_patcher-----------
----------begin_max5_patcher---------- 455.3ocuU01SCBCD9yvuhl9YboktofeyeGFioLNmcBsKzhN03+coGPlujs0Y lPBE50q8dddtii2iinElsfkRtlbKIJ583nHzj2Pzv7HZsb6xJoEcipgWLEqo I8K4fsNzbITQXiVevncV0afeEd5L1fYUI5Z21uX9nqajtkOpzqtuAV55wAWH 51BYdteTbkeLkMiQtaXK51ZktBbHdR+RH0xZLjzaZTxJ5N2MstQ+4CV6M4dc CzGTZgTuhRtyu5Gww9gj.UjhVmyno+ljhiSRNajdGhj7ohJ0f0JWA+J6dUZ3 o1rCw5KWfrF2IQjNaQ2jr+8b6eSL1Skds7IPabPWti4uOgp97.jFQduBcj5d wIpMo6SadnxHczjwWNmJkWk5hW35CmEf.0+XA+7pOryGsaeSg0E30IP9i2sH C+rIO671RTbv9HI6dpz+n9.iOsRo+4uPPJ3s+c0yZZaVNd5C+FfriEkf0ozR mpqa5Ne3eymGUkk.t7nDVprxhJnb+YwPQiH.zLexPim27iflrICMYAnM4SFZ xCotgMovgGBb3+A3z+QlbylmgF6vYhHoqYzZSie5kI3TkteJdhzF3Y0n+Yw9 S6i3OMIsDwJ -----------end_max5_patcher-----------
I turn on the metro, I bang the uzi. I’d expect the metro to go on (more or less) smoothly, but it doesn’t – it stops until the Uzi fires… I have tried this with different scheduler setting, including SIAI and audio on, with no effect… any clue? How can I benefit from the separate schedulers?
It would be amazing to use different top-level patchers, if only we could save object states in pattrstorage from different patcher hierarchies. With pattrmarker you can only send messages to objects in all kind of hierarchies for now, not save states for said objects. It’s a pitty since otherwise projects are very handy for using several top-level patchers.
in fact you can, with pattrmarker. otoh, I can’t seem to be able to have pattrstorage directly talking to a named pattr in a different patcher hierarchy – I need a pattr in the same hierarchy as pattrstorage, bound to my "remote" pattr. The explicit subscription mechanism doesn’t help either…
Hopefully the following clarifies the reason your patches block each other. The issue is threading synchronization. We don’t permit totally free separate threads here. Possibly will be more flexible in the future, but not soon.
1. In absence of SIAI, all schedulers are run in the main timer thread
2. If SIAI is enabled, each top level patcher is run in a separate thread, alternating running scheduler and audio in the same audio thread for that top level patcher.
3. All audio threads wait for all other audio threads to finish before computing their next vector of samples, and running their scheduler if SIAI (where your example blocks even if running in separate audio threads)
Someday we may permit multiple scheduler threads which are not tied to Audio threads. We would not need to synchronize those, but we do need to synchronize for audio, just like we do in poly~ as you mention.
In the meantime, your best bet for this kind of totally asynchronous processing would be to use multiple instances of Max running and communicate via udpsend/receive or similar for true isolation.
thank you for the clarification. It totally makes sense.
So, I’ll just keep my finger crossed for freer parallelism in some future… – seriously, could you guys remove the "output stuff only from the regular threads" limitation at some point?!? ;)
would this be an appropriate workaround for running a single instance of an audio patch (poly_loadme in this example) on a specified core?
----------begin_max5_patcher---------- 561.3ocyV1rbaBCDG+L9oXGtjKtdPBi+HmbeE50NYxHCarUGPhAIpcRlzm8J s.MjOsMwSSN3EzpUn+5m1Ux2OJHbsdOZBgKgeBAA2OJHfb4cDz1NHrPrOMWX nvBS0EEnxFNtoOKt2R9+AVlKRQ3B9EvNocKX2hfptXMVA5anVo5JDJjpZCnU HraK5Z66nTXS2BRCf6KwTKlAVMTUqlzMK4RElpqUzTE25z8wkpbzR5h8nScs syaTq2azJqRTfjR+dkTj28kKqPia4HrRs55J2j2vhkKmDMFXK71nVCbU2X7x Up1zOdJHVBYmMy+X5hdCwK.i7NR.L9jNcIyHEoW+quEG5c8vnQdy3y0lQ76u Y70XK3k3LtkjwMORVN.fxGBPU3N2XeAOEkknJCXgG+5lcv0cSv1aKwlEcX36 kg0RDNknMi4s7nSKCicFIhqtgPRQsE+zoRS02hjg.knyHTpuSBQuQVB+U4Q7 oyi0B0lvwO9T5KIOHhlQHZ5rAfH9xyHhx0hrBzX.9mdVSLgj47gfjEmyRIc9 s+A71qanCrpTTIxywbfAq9sVlhFHFVYEUaPKDeB4WSOcxYjaT9t6+F86HNcJ gPJe4PNdhOuOSoARW57r+cBM4d+OEzFccUZ2Rnsv1cq8+l+LzXkJ5Z99AwdR PakYYnp+sVExrRsqBqUDvUu519wpIWkjCKGRSQmllRXSRbG9M0a4S6d+ipzE GA8nky+O58rMq2PSy+.Zx03gQ+kM7LpQ -----------end_max5_patcher-----------
I’m curious in the answer to this. I’ve been currently looking at Alex Harker’s dynamicdsp objects to try putting a very hungry vst (kontakt) on it’s own core, while running a big max patch.
Regarding Joshua Kit Clayton’s suggestion:
"use multiple instances of Max"
Does this mean:
a) discrete installations of Max open simultaneously or
b) multiple "top-level" patches opened from a single Max installation?
I think JKC means (b).
Like Rodrigo I am interested in running Kontakt within Max, and am working on patches that either:
1) contain multiple vst~ objects each hosting different Kontakt sample libraries
2) multiple "top-level" patches that each contain one vst~ (or two, one with a Kontakt sample library and another running reverb)
I am leaning towards (2), both for UI reasons and because I think this will allow MaxMSP to more efficiently use both independent threads and multiple cores. [In either case the vst~ and dac~ objects are inside poly~ objects so that they can be muted]. Is either of these methods better? Would Scheduler In Audio Interrupt (SIAI) make option (1) essentially the same as (2)?
Will using multiple "top-level" patches as in (b) and (2) above increase, decrease, or not affect Max6.1′s ability to distribute audio processing to different cores?
Max documentation mentions "top-level patchers" but I don’t know if this is ever defined. Since Max6 "maintains each top-level patcher’s audio in a separate DSP chain" a clear definition would be helpful for me. Can "top level" patch be defined as:
Top Level: Any Max patch that is not a [patcher] [bpatcher] [poly] [poly~] [gen~] [jit.gen] or other named abstraction within another Max patch.
Does this include patchers that are opened with a ; max openfile message?
@john: For Andrea’s specific example I meant (a), but for what you describe, I think (b) should work for your purposes.
I think SIAI will not affect your described use case significantly. That is just whether or not the event scheduler will use multiple cores together with the audio threads (we only parallelize the audio threads for multiple top level patchers. If scheduler is in audio interrupt, then the event processing is also distributed). With a vst~ device, most of your processing will likely be in the calculation of audio, not events, which, if parallel processing is enabled in the audio status window, allow Max to distribute multiple top level patchers’ audio processing over the cores.
Re: Top level patchers, your assumptions are correct.
The point for me is to have optimized processing but with a single, global GUI. The tabbed patchers addresses the problem of having many controls on the screen, while maintaining a fast access to every part (rather than having to load another patcher, editing and not forgetting to save as it is with poly~). Therefore the possibility to distribute on a tab basis would be a real plus. I’ll have a look at Alex Harker’s dynamicdsp objects.
Yeah, multiple GUI/patchers at top level is not great.
I’m gonna implement some dynamicdsp stuff, but it’s just a matter of figuring what bits of the patch to stick in there for maximum impact.
+1 for Roald’s tab proposal. Perhaps there could be an option to select whether a tab runs its own schedulers or has a ‘parent’.
Posting this just after having re-exported 4 standalone apps included in my system for the gigamillionth time ;)
Having them separated from the core audio/openGL patch increases my rendering framerate by 50%.
Poor C74′s… They ‘re not even done giving us 64bit and there we go again demanding multithreading ;)