Howdy,
I just read in an answer from Christof to Alexandre : "never ever send a Pd message directly from a perform routine ! Always use a clock !" But I never took the time to deeply understand Pd's inner working and am not sure why it is bad practice. Not sure what could be the consequences of doing this, but it might explain a random bug I've been experiencing with one of my externals. I wrote a couple of plugins with juce so I'm aware of the most basic good lock-free programming practices in C++ (which seems to boil down to : use atomic variables in C++, or a lock-free queue if needed). Could Christof's advice be related to threading issues ? I thought I'd read somewhere that everything was running on the same thread in Pd (at least the "backend", maybe not the GUI), but please correct me if I'm wrong. Also, I'm having a hard time finding any doc about clocks, is there a known object that uses them that I could take as an example ? Sorry if this has been brought up before (which is probably the case), and thanks in advance for your enlightenments.
Cheers,
Joseph Larralde -- freelance developer www.josephlarralde.fr
Hi Joseph -
If you send a message from within the DSP chain that causes the chain itself to be rebuilt it will crash Pd. That's not a thread problem, but a (sort of) reentrancy problem. If you're the only user of your object you can simply avoid doing that, but if you're publishing your object it might bite someone else.
The built-in objects "delay", "metro" and "pipe" use clocks in various ways.
cheers
Miller
On 8/21/23 18:02, Joseph Larralde wrote:
Howdy,
I just read in an answer from Christof to Alexandre : "never ever send a Pd message directly from a perform routine ! Always use a clock !" But I never took the time to deeply understand Pd's inner working and am not sure why it is bad practice. Not sure what could be the consequences of doing this, but it might explain a random bug I've been experiencing with one of my externals. I wrote a couple of plugins with juce so I'm aware of the most basic good lock-free programming practices in C++ (which seems to boil down to : use atomic variables in C++, or a lock-free queue if needed). Could Christof's advice be related to threading issues ? I thought I'd read somewhere that everything was running on the same thread in Pd (at least the "backend", maybe not the GUI), but please correct me if I'm wrong. Also, I'm having a hard time finding any doc about clocks, is there a known object that uses them that I could take as an example ? Sorry if this has been brought up before (which is probably the case), and thanks in advance for your enlightenments.
Cheers,
Joseph Larralde
freelance developer https://urldefense.com/v3/__http://www.josephlarralde.fr__;!!Mih3wA!BKes5WdO...
Pd-dev mailing list Pd-dev@lists.iem.at https://urldefense.com/v3/__https://lists.puredata.info/listinfo/pd-dev__;!!...
See bang~ in pure-data/src/d_misc.c for an example that uses a clock to send a message from DSP.
On 21/08/2023 18:02, Miller Puckette wrote:
The built-in objects "delay", "metro" and "pipe" use clocks in various ways.
On 8/21/23 18:02, Joseph Larralde wrote:
I just read in an answer from Christof to Alexandre : "never ever send a Pd message directly from a perform routine ! Always use a clock !"
Hmm, I see ... unfortunately my random bug is totally unrelated to this weakness of my code. Thanks Miller for the explanation and pointers to examples ! And thanks Claude for the extra example. I'll check all my objects to see if there are other ones I can consolidate.
Cheers !
Joseph
Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit :
See bang~ in pure-data/src/d_misc.c for an example that uses a clock to send a message from DSP.
On 21/08/2023 18:02, Miller Puckette wrote:
The built-in objects "delay", "metro" and "pipe" use clocks in various ways.
On 8/21/23 18:02, Joseph Larralde wrote:
I just read in an answer from Christof to Alexandre : "never ever send a Pd message directly from a perform routine ! Always use a clock !"
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
To expand on Miller's reply:
Conceptually, messaging and DSP are two separate domains. Sending a message from a perform routine violates this separation. Instead you should use a clock with delay 0 to defer the message to the begin of the next scheduler tick.
Miller already mentioned the greatest danger, but there are other, more subtle issues. DSP objects typically operate on the premise that the object's state won't change from the outside during the perform routine. For example, imagine a delay object with a buffer that can be resized with a message; by sending a Pd message from the perform routine, it might accidentally feed back into the object and reallocate the buffer while still in progress.
Unfortunately, very little of this is documented. Ideally, this should be covered in the externals-how-to (https://github.com/pure-data/externals-howto); I just added an item on my (long) TODO list.
Finally, although Pd is currently single-threaded, this could change in the future. FWIW, here is a PoC for multi-threaded DSP: https://github.com/spacechild1/pure-data/tree/multi-threading. This is only possible because perform routines may only use a restricted set of API functions - which, in my fork, are annoted with the (empty) THREADSAFE macro (and made thread-safe, if necessary).
Christof
On 21.08.2023 20:55, Joseph Larralde wrote:
Hmm, I see ... unfortunately my random bug is totally unrelated to this weakness of my code. Thanks Miller for the explanation and pointers to examples ! And thanks Claude for the extra example. I'll check all my objects to see if there are other ones I can consolidate.
Cheers !
Joseph
Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit :
See bang~ in pure-data/src/d_misc.c for an example that uses a clock to send a message from DSP.
On 21/08/2023 18:02, Miller Puckette wrote:
The built-in objects "delay", "metro" and "pipe" use clocks in various ways.
On 8/21/23 18:02, Joseph Larralde wrote:
I just read in an answer from Christof to Alexandre : "never ever send a Pd message directly from a perform routine ! Always use a clock !"
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
How well does it work? It looks like the repo is based off of 0.52? Multithreaded DSP would have been much higher on my list than multi-channel, so I'm wondering if I could get away with using your tree as my basis for a while :)
- d
On Tue, 22 Aug 2023 at 01:17, Christof Ressi info@christofressi.com wrote:
To expand on Miller's reply:
Conceptually, messaging and DSP are two separate domains. Sending a message from a perform routine violates this separation. Instead you should use a clock with delay 0 to defer the message to the begin of the next scheduler tick.
Miller already mentioned the greatest danger, but there are other, more subtle issues. DSP objects typically operate on the premise that the object's state won't change from the outside during the perform routine. For example, imagine a delay object with a buffer that can be resized with a message; by sending a Pd message from the perform routine, it might accidentally feed back into the object and reallocate the buffer while still in progress.
Unfortunately, very little of this is documented. Ideally, this should be covered in the externals-how-to (https://github.com/pure-data/externals-howto); I just added an item on my (long) TODO list.
Finally, although Pd is currently single-threaded, this could change in the future. FWIW, here is a PoC for multi-threaded DSP: https://github.com/spacechild1/pure-data/tree/multi-threading. This is only possible because perform routines may only use a restricted set of API functions - which, in my fork, are annoted with the (empty) THREADSAFE macro (and made thread-safe, if necessary).
Christof
On 21.08.2023 20:55, Joseph Larralde wrote:
Hmm, I see ... unfortunately my random bug is totally unrelated to this weakness of my code. Thanks Miller for the explanation and pointers to examples ! And thanks Claude for the extra example. I'll check all my objects to see if there are other ones I can consolidate.
Cheers !
Joseph
Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit :
See bang~ in pure-data/src/d_misc.c for an example that uses a clock to send a message from DSP.
On 21/08/2023 18:02, Miller Puckette wrote:
The built-in objects "delay", "metro" and "pipe" use clocks in various ways.
On 8/21/23 18:02, Joseph Larralde wrote:
I just read in an answer from Christof to Alexandre : "never ever send a Pd message directly from a perform routine ! Always use a clock !"
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
How well does it work?
It seems to work quite well. With synthetic benchmarks I can get a 6x speedup on my 8 core machine, but I need to do some more practical testing and benchmarking.
It looks like the repo is based off of 0.52?
I think it's based on 0.53. I want to rebase it on 0.54, but there are lots of conflicts I need to resolve. It's definitely on my TODO list. That's also why I haven't really made a formal announcement yet.
Multithreaded DSP would have been much higher on my list than multi-channel,
Priorities are very subjective. Personally, I don't really think that multithreaded DSP has high priority for the general user base, as many patches seem to run fine on a single CPU. However, I do have projects that reach or exceed the limits of a single CPU - even on a beefy machine -, that's why I started working on this.
so I'm wondering if I could get away with using your tree as my basis for a while :)
Actually, it would be great to have some testers apart from myself!
Christof
On 22.08.2023 10:32, Day Rush wrote:
How well does it work? It looks like the repo is based off of 0.52? Multithreaded DSP would have been much higher on my list than multi-channel, so I'm wondering if I could get away with using your tree as my basis for a while :)
- d
On Tue, 22 Aug 2023 at 01:17, Christof Ressi info@christofressi.com wrote:
To expand on Miller's reply: Conceptually, messaging and DSP are two separate domains. Sending a message from a perform routine violates this separation. Instead you should use a clock with delay 0 to defer the message to the begin of the next scheduler tick. Miller already mentioned the greatest danger, but there are other, more subtle issues. DSP objects typically operate on the premise that the object's state won't change from the outside during the perform routine. For example, imagine a delay object with a buffer that can be resized with a message; by sending a Pd message from the perform routine, it might accidentally feed back into the object and reallocate the buffer while still in progress. Unfortunately, very little of this is documented. Ideally, this should be covered in the externals-how-to (https://github.com/pure-data/externals-howto); I just added an item on my (long) TODO list. Finally, although Pd is currently single-threaded, this could change in the future. FWIW, here is a PoC for multi-threaded DSP: https://github.com/spacechild1/pure-data/tree/multi-threading. This is only possible because perform routines may only use a restricted set of API functions - which, in my fork, are annoted with the (empty) THREADSAFE macro (and made thread-safe, if necessary). Christof On 21.08.2023 20:55, Joseph Larralde wrote: > Hmm, I see ... unfortunately my random bug is totally unrelated to > this weakness of my code. > Thanks Miller for the explanation and pointers to examples ! > And thanks Claude for the extra example. > I'll check all my objects to see if there are other ones I can > consolidate. > > Cheers ! > > Joseph > > Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit : >> See bang~ in pure-data/src/d_misc.c for an example that uses a clock >> to send a message from DSP. >> >> On 21/08/2023 18:02, Miller Puckette wrote: >>> The built-in objects "delay", "metro" and "pipe" use clocks in >>> various ways. >>> >>> On 8/21/23 18:02, Joseph Larralde wrote: >>>> I just read in an answer from Christof to Alexandre : "never ever >>>> send a Pd message directly from a perform routine ! Always use a >>>> clock !" >> >> >> >> >> _______________________________________________ >> Pd-dev mailing list >> Pd-dev@lists.iem.at >> https://lists.puredata.info/listinfo/pd-dev > > > > > _______________________________________________ > Pd-dev mailing list > Pd-dev@lists.iem.at > https://lists.puredata.info/listinfo/pd-dev _______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
-- GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Thanks Christof for the additional insight. I've always been puzzled by the fact that everything runs on a single thread in Pd. I guess this single thread IS the audio thread because it processes audio, and I've always heard that one must never perform too many non-audio operations during an audio callback. But as you say, Pd runs fine for the general user base which I am part of. I'll probably give your version a try if I hit the limits with my current (rapidly growing) project running on a Pi 3 B+, but can't make any promises with my current schedule. Thanks for your work anyways.
Best,
Joseph Larralde -- freelance developer www.josephlarralde.fr
Le 22/08/2023 à 11:55, Christof Ressi a écrit :
How well does it work?
It seems to work quite well. With synthetic benchmarks I can get a 6x speedup on my 8 core machine, but I need to do some more practical testing and benchmarking.
It looks like the repo is based off of 0.52?
I think it's based on 0.53. I want to rebase it on 0.54, but there are lots of conflicts I need to resolve. It's definitely on my TODO list. That's also why I haven't really made a formal announcement yet.
Multithreaded DSP would have been much higher on my list than multi-channel,
Priorities are very subjective. Personally, I don't really think that multithreaded DSP has high priority for the general user base, as many patches seem to run fine on a single CPU. However, I do have projects that reach or exceed the limits of a single CPU - even on a beefy machine -, that's why I started working on this.
so I'm wondering if I could get away with using your tree as my basis for a while :)
Actually, it would be great to have some testers apart from myself!
Christof
On 22.08.2023 10:32, Day Rush wrote:
How well does it work? It looks like the repo is based off of 0.52? Multithreaded DSP would have been much higher on my list than multi-channel, so I'm wondering if I could get away with using your tree as my basis for a while :)
- d
On Tue, 22 Aug 2023 at 01:17, Christof Ressi info@christofressi.com wrote:
To expand on Miller's reply: Conceptually, messaging and DSP are two separate domains. Sending a message from a perform routine violates this separation. Instead you should use a clock with delay 0 to defer the message to the begin of the next scheduler tick. Miller already mentioned the greatest danger, but there are other, more subtle issues. DSP objects typically operate on the premise that the object's state won't change from the outside during the perform routine. For example, imagine a delay object with a buffer that can be resized with a message; by sending a Pd message from the perform routine, it might accidentally feed back into the object and reallocate the buffer while still in progress. Unfortunately, very little of this is documented. Ideally, this should be covered in the externals-how-to (https://github.com/pure-data/externals-howto); I just added an item on my (long) TODO list. Finally, although Pd is currently single-threaded, this could change in the future. FWIW, here is a PoC for multi-threaded DSP: https://github.com/spacechild1/pure-data/tree/multi-threading. This is only possible because perform routines may only use a restricted set of API functions - which, in my fork, are annoted with the (empty) THREADSAFE macro (and made thread-safe, if necessary). Christof On 21.08.2023 20:55, Joseph Larralde wrote: > Hmm, I see ... unfortunately my random bug is totally unrelated to > this weakness of my code. > Thanks Miller for the explanation and pointers to examples ! > And thanks Claude for the extra example. > I'll check all my objects to see if there are other ones I can > consolidate. > > Cheers ! > > Joseph > > Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit : >> See bang~ in pure-data/src/d_misc.c for an example that uses a clock >> to send a message from DSP. >> >> On 21/08/2023 18:02, Miller Puckette wrote: >>> The built-in objects "delay", "metro" and "pipe" use clocks in >>> various ways. >>> >>> On 8/21/23 18:02, Joseph Larralde wrote: >>>> I just read in an answer from Christof to Alexandre : "never ever >>>> send a Pd message directly from a perform routine ! Always use a >>>> clock !" >> >> >> >> >> _______________________________________________ >> Pd-dev mailing list >> Pd-dev@lists.iem.at >> https://lists.puredata.info/listinfo/pd-dev > > > > > _______________________________________________ > Pd-dev mailing list > Pd-dev@lists.iem.at > https://lists.puredata.info/listinfo/pd-dev _______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
-- GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
I've always been puzzled by the fact that everything runs on a single thread in Pd.
By default, Pd operates in "polling mode", i.e. the scheduler runs in its own thread (the main thread) and communicates with the audio callback via two lockfree ringbuffers (one for input, one for output). The size of the ringbuffers is set by the ominous "delay" parameter in the audio settings. The actual audio thread only reads/writes samples from/to the ringbuffers.
If Pd operates in "callback mode" (= "callbacks" is ticked in the audio settings), the scheduler runs directly in the audio callback. You can save a little bit of latency, but it is less forgiving to CPU spikes or non-realtime-safe operations.
Christof
On 22.08.2023 15:08, Joseph Larralde wrote:
Thanks Christof for the additional insight. I've always been puzzled by the fact that everything runs on a single thread in Pd. I guess this single thread IS the audio thread because it processes audio, and I've always heard that one must never perform too many non-audio operations during an audio callback. But as you say, Pd runs fine for the general user base which I am part of. I'll probably give your version a try if I hit the limits with my current (rapidly growing) project running on a Pi 3 B+, but can't make any promises with my current schedule. Thanks for your work anyways.
Best, Joseph Larralde -- freelance developer www.josephlarralde.fr Le 22/08/2023 à 11:55, Christof Ressi a écrit :
How well does it work?
It seems to work quite well. With synthetic benchmarks I can get a 6x speedup on my 8 core machine, but I need to do some more practical testing and benchmarking.
It looks like the repo is based off of 0.52?
I think it's based on 0.53. I want to rebase it on 0.54, but there are lots of conflicts I need to resolve. It's definitely on my TODO list. That's also why I haven't really made a formal announcement yet.
Multithreaded DSP would have been much higher on my list than multi-channel,
Priorities are very subjective. Personally, I don't really think that multithreaded DSP has high priority for the general user base, as many patches seem to run fine on a single CPU. However, I do have projects that reach or exceed the limits of a single CPU - even on a beefy machine -, that's why I started working on this.
so I'm wondering if I could get away with using your tree as my basis for a while :)
Actually, it would be great to have some testers apart from myself!
Christof
On 22.08.2023 10:32, Day Rush wrote:
How well does it work? It looks like the repo is based off of 0.52? Multithreaded DSP would have been much higher on my list than multi-channel, so I'm wondering if I could get away with using your tree as my basis for a while :)
- d
On Tue, 22 Aug 2023 at 01:17, Christof Ressi info@christofressi.com wrote:
To expand on Miller's reply: Conceptually, messaging and DSP are two separate domains. Sending a message from a perform routine violates this separation. Instead you should use a clock with delay 0 to defer the message to the begin of the next scheduler tick. Miller already mentioned the greatest danger, but there are other, more subtle issues. DSP objects typically operate on the premise that the object's state won't change from the outside during the perform routine. For example, imagine a delay object with a buffer that can be resized with a message; by sending a Pd message from the perform routine, it might accidentally feed back into the object and reallocate the buffer while still in progress. Unfortunately, very little of this is documented. Ideally, this should be covered in the externals-how-to (https://github.com/pure-data/externals-howto); I just added an item on my (long) TODO list. Finally, although Pd is currently single-threaded, this could change in the future. FWIW, here is a PoC for multi-threaded DSP: https://github.com/spacechild1/pure-data/tree/multi-threading. This is only possible because perform routines may only use a restricted set of API functions - which, in my fork, are annoted with the (empty) THREADSAFE macro (and made thread-safe, if necessary). Christof On 21.08.2023 20:55, Joseph Larralde wrote: > Hmm, I see ... unfortunately my random bug is totally unrelated to > this weakness of my code. > Thanks Miller for the explanation and pointers to examples ! > And thanks Claude for the extra example. > I'll check all my objects to see if there are other ones I can > consolidate. > > Cheers ! > > Joseph > > Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit : >> See bang~ in pure-data/src/d_misc.c for an example that uses a clock >> to send a message from DSP. >> >> On 21/08/2023 18:02, Miller Puckette wrote: >>> The built-in objects "delay", "metro" and "pipe" use clocks in >>> various ways. >>> >>> On 8/21/23 18:02, Joseph Larralde wrote: >>>> I just read in an answer from Christof to Alexandre : "never ever >>>> send a Pd message directly from a perform routine ! Always use a >>>> clock !" >> >> >> >> >> _______________________________________________ >> Pd-dev mailing list >> Pd-dev@lists.iem.at >> https://lists.puredata.info/listinfo/pd-dev > > > > > _______________________________________________ > Pd-dev mailing list > Pd-dev@lists.iem.at > https://lists.puredata.info/listinfo/pd-dev _______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
-- GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Wow, thanks again Christof, this greatly improves my understanding of Pd's engine. Indeed, I never use callback mode because everytime I did in the past I got some xruns, but had no clue about what was happening behind the scene. I feel a bit ashamed, I'm pretty sure I could have figured this out by reading more posts / docs / code ... I'm very grateful to both of you for taking the time to explain this in detail, and I hope this will benefit other users on the list.
Best regards,
Joseph
Le 22/08/2023 à 17:22, Christof Ressi a écrit :
I've always been puzzled by the fact that everything runs on a single thread in Pd.
By default, Pd operates in "polling mode", i.e. the scheduler runs in its own thread (the main thread) and communicates with the audio callback via two lockfree ringbuffers (one for input, one for output). The size of the ringbuffers is set by the ominous "delay" parameter in the audio settings. The actual audio thread only reads/writes samples from/to the ringbuffers.
If Pd operates in "callback mode" (= "callbacks" is ticked in the audio settings), the scheduler runs directly in the audio callback. You can save a little bit of latency, but it is less forgiving to CPU spikes or non-realtime-safe operations.
Christof
On 22.08.2023 15:08, Joseph Larralde wrote:
Thanks Christof for the additional insight. I've always been puzzled by the fact that everything runs on a single thread in Pd. I guess this single thread IS the audio thread because it processes audio, and I've always heard that one must never perform too many non-audio operations during an audio callback. But as you say, Pd runs fine for the general user base which I am part of. I'll probably give your version a try if I hit the limits with my current (rapidly growing) project running on a Pi 3 B+, but can't make any promises with my current schedule. Thanks for your work anyways.
Best, Joseph Larralde -- freelance developer www.josephlarralde.fr Le 22/08/2023 à 11:55, Christof Ressi a écrit :
How well does it work?
It seems to work quite well. With synthetic benchmarks I can get a 6x speedup on my 8 core machine, but I need to do some more practical testing and benchmarking.
It looks like the repo is based off of 0.52?
I think it's based on 0.53. I want to rebase it on 0.54, but there are lots of conflicts I need to resolve. It's definitely on my TODO list. That's also why I haven't really made a formal announcement yet.
Multithreaded DSP would have been much higher on my list than multi-channel,
Priorities are very subjective. Personally, I don't really think that multithreaded DSP has high priority for the general user base, as many patches seem to run fine on a single CPU. However, I do have projects that reach or exceed the limits of a single CPU - even on a beefy machine -, that's why I started working on this.
so I'm wondering if I could get away with using your tree as my basis for a while :)
Actually, it would be great to have some testers apart from myself!
Christof
On 22.08.2023 10:32, Day Rush wrote:
How well does it work? It looks like the repo is based off of 0.52? Multithreaded DSP would have been much higher on my list than multi-channel, so I'm wondering if I could get away with using your tree as my basis for a while :)
- d
On Tue, 22 Aug 2023 at 01:17, Christof Ressi info@christofressi.com wrote:
To expand on Miller's reply: Conceptually, messaging and DSP are two separate domains. Sending a message from a perform routine violates this separation. Instead you should use a clock with delay 0 to defer the message to the begin of the next scheduler tick. Miller already mentioned the greatest danger, but there are other, more subtle issues. DSP objects typically operate on the premise that the object's state won't change from the outside during the perform routine. For example, imagine a delay object with a buffer that can be resized with a message; by sending a Pd message from the perform routine, it might accidentally feed back into the object and reallocate the buffer while still in progress. Unfortunately, very little of this is documented. Ideally, this should be covered in the externals-how-to (https://github.com/pure-data/externals-howto); I just added an item on my (long) TODO list. Finally, although Pd is currently single-threaded, this could change in the future. FWIW, here is a PoC for multi-threaded DSP: https://github.com/spacechild1/pure-data/tree/multi-threading. This is only possible because perform routines may only use a restricted set of API functions - which, in my fork, are annoted with the (empty) THREADSAFE macro (and made thread-safe, if necessary). Christof On 21.08.2023 20:55, Joseph Larralde wrote: > Hmm, I see ... unfortunately my random bug is totally unrelated to > this weakness of my code. > Thanks Miller for the explanation and pointers to examples ! > And thanks Claude for the extra example. > I'll check all my objects to see if there are other ones I can > consolidate. > > Cheers ! > > Joseph > > Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit : >> See bang~ in pure-data/src/d_misc.c for an example that uses a clock >> to send a message from DSP. >> >> On 21/08/2023 18:02, Miller Puckette wrote: >>> The built-in objects "delay", "metro" and "pipe" use clocks in >>> various ways. >>> >>> On 8/21/23 18:02, Joseph Larralde wrote: >>>> I just read in an answer from Christof to Alexandre : "never ever >>>> send a Pd message directly from a perform routine ! Always use a >>>> clock !" >> >> >> >> >> _______________________________________________ >> Pd-dev mailing list >> Pd-dev@lists.iem.at >> https://lists.puredata.info/listinfo/pd-dev > > > > > _______________________________________________ > Pd-dev mailing list > Pd-dev@lists.iem.at > https://lists.puredata.info/listinfo/pd-dev _______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
-- GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Glad that I could help! Very little of this is really documented (accurately). Personally, I figured this out by reading the source code.
Ideally, we should improve the official documentation in http://msp.ucsd.edu/Pd_documentation/x3.htm#s1.0. Some things are outdated, misleading or just plain wrong (in particular the section "audio buffer size and block size"). I just put this on my (ever-growing) TODO list.
Christof
On 23.08.2023 16:38, Joseph Larralde wrote:
Wow, thanks again Christof, this greatly improves my understanding of Pd's engine. Indeed, I never use callback mode because everytime I did in the past I got some xruns, but had no clue about what was happening behind the scene. I feel a bit ashamed, I'm pretty sure I could have figured this out by reading more posts / docs / code ... I'm very grateful to both of you for taking the time to explain this in detail, and I hope this will benefit other users on the list.
Best regards, Joseph Le 22/08/2023 à 17:22, Christof Ressi a écrit :
I've always been puzzled by the fact that everything runs on a single thread in Pd.
By default, Pd operates in "polling mode", i.e. the scheduler runs in its own thread (the main thread) and communicates with the audio callback via two lockfree ringbuffers (one for input, one for output). The size of the ringbuffers is set by the ominous "delay" parameter in the audio settings. The actual audio thread only reads/writes samples from/to the ringbuffers.
If Pd operates in "callback mode" (= "callbacks" is ticked in the audio settings), the scheduler runs directly in the audio callback. You can save a little bit of latency, but it is less forgiving to CPU spikes or non-realtime-safe operations.
Christof
On 22.08.2023 15:08, Joseph Larralde wrote:
Thanks Christof for the additional insight. I've always been puzzled by the fact that everything runs on a single thread in Pd. I guess this single thread IS the audio thread because it processes audio, and I've always heard that one must never perform too many non-audio operations during an audio callback. But as you say, Pd runs fine for the general user base which I am part of. I'll probably give your version a try if I hit the limits with my current (rapidly growing) project running on a Pi 3 B+, but can't make any promises with my current schedule. Thanks for your work anyways.
Best, Joseph Larralde -- freelance developer www.josephlarralde.fr Le 22/08/2023 à 11:55, Christof Ressi a écrit :
How well does it work?
It seems to work quite well. With synthetic benchmarks I can get a 6x speedup on my 8 core machine, but I need to do some more practical testing and benchmarking.
It looks like the repo is based off of 0.52?
I think it's based on 0.53. I want to rebase it on 0.54, but there are lots of conflicts I need to resolve. It's definitely on my TODO list. That's also why I haven't really made a formal announcement yet.
Multithreaded DSP would have been much higher on my list than multi-channel,
Priorities are very subjective. Personally, I don't really think that multithreaded DSP has high priority for the general user base, as many patches seem to run fine on a single CPU. However, I do have projects that reach or exceed the limits of a single CPU - even on a beefy machine -, that's why I started working on this.
so I'm wondering if I could get away with using your tree as my basis for a while :)
Actually, it would be great to have some testers apart from myself!
Christof
On 22.08.2023 10:32, Day Rush wrote:
How well does it work? It looks like the repo is based off of 0.52? Multithreaded DSP would have been much higher on my list than multi-channel, so I'm wondering if I could get away with using your tree as my basis for a while :)
- d
On Tue, 22 Aug 2023 at 01:17, Christof Ressi info@christofressi.com wrote:
To expand on Miller's reply: Conceptually, messaging and DSP are two separate domains. Sending a message from a perform routine violates this separation. Instead you should use a clock with delay 0 to defer the message to the begin of the next scheduler tick. Miller already mentioned the greatest danger, but there are other, more subtle issues. DSP objects typically operate on the premise that the object's state won't change from the outside during the perform routine. For example, imagine a delay object with a buffer that can be resized with a message; by sending a Pd message from the perform routine, it might accidentally feed back into the object and reallocate the buffer while still in progress. Unfortunately, very little of this is documented. Ideally, this should be covered in the externals-how-to (https://github.com/pure-data/externals-howto); I just added an item on my (long) TODO list. Finally, although Pd is currently single-threaded, this could change in the future. FWIW, here is a PoC for multi-threaded DSP: https://github.com/spacechild1/pure-data/tree/multi-threading. This is only possible because perform routines may only use a restricted set of API functions - which, in my fork, are annoted with the (empty) THREADSAFE macro (and made thread-safe, if necessary). Christof On 21.08.2023 20:55, Joseph Larralde wrote: > Hmm, I see ... unfortunately my random bug is totally unrelated to > this weakness of my code. > Thanks Miller for the explanation and pointers to examples ! > And thanks Claude for the extra example. > I'll check all my objects to see if there are other ones I can > consolidate. > > Cheers ! > > Joseph > > Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit : >> See bang~ in pure-data/src/d_misc.c for an example that uses a clock >> to send a message from DSP. >> >> On 21/08/2023 18:02, Miller Puckette wrote: >>> The built-in objects "delay", "metro" and "pipe" use clocks in >>> various ways. >>> >>> On 8/21/23 18:02, Joseph Larralde wrote: >>>> I just read in an answer from Christof to Alexandre : "never ever >>>> send a Pd message directly from a perform routine ! Always use a >>>> clock !" >> >> >> >> >> _______________________________________________ >> Pd-dev mailing list >> Pd-dev@lists.iem.at >> https://lists.puredata.info/listinfo/pd-dev > > > > > _______________________________________________ > Pd-dev mailing list > Pd-dev@lists.iem.at > https://lists.puredata.info/listinfo/pd-dev _______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
-- GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
For what it's worth, I actually get fewer xruns in callback mode, but I am running computation-heavy externals for much of my sound design so YMMV. I also bump the sound-generation process up to realtime priority.
On Wed, 23 Aug 2023 at 15:39, Joseph Larralde joseph.larralde@gmail.com wrote:
Wow, thanks again Christof, this greatly improves my understanding of Pd's engine. Indeed, I never use callback mode because everytime I did in the past I got some xruns, but had no clue about what was happening behind the scene. I feel a bit ashamed, I'm pretty sure I could have figured this out by reading more posts / docs / code ... I'm very grateful to both of you for taking the time to explain this in detail, and I hope this will benefit other users on the list.
Best regards,
Joseph
Le 22/08/2023 à 17:22, Christof Ressi a écrit :
I've always been puzzled by the fact that everything runs on a single thread in Pd.
By default, Pd operates in "polling mode", i.e. the scheduler runs in its own thread (the main thread) and communicates with the audio callback via two lockfree ringbuffers (one for input, one for output). The size of the ringbuffers is set by the ominous "delay" parameter in the audio settings. The actual audio thread only reads/writes samples from/to the ringbuffers.
If Pd operates in "callback mode" (= "callbacks" is ticked in the audio settings), the scheduler runs directly in the audio callback. You can save a little bit of latency, but it is less forgiving to CPU spikes or non-realtime-safe operations.
Christof
On 22.08.2023 15:08, Joseph Larralde wrote:
Thanks Christof for the additional insight. I've always been puzzled by the fact that everything runs on a single thread in Pd. I guess this single thread IS the audio thread because it processes audio, and I've always heard that one must never perform too many non-audio operations during an audio callback. But as you say, Pd runs fine for the general user base which I am part of. I'll probably give your version a try if I hit the limits with my current (rapidly growing) project running on a Pi 3 B+, but can't make any promises with my current schedule. Thanks for your work anyways.
Best,
Joseph Larralde
freelance developerwww.josephlarralde.fr
Le 22/08/2023 à 11:55, Christof Ressi a écrit :
How well does it work?
It seems to work quite well. With synthetic benchmarks I can get a 6x speedup on my 8 core machine, but I need to do some more practical testing and benchmarking.
It looks like the repo is based off of 0.52?
I think it's based on 0.53. I want to rebase it on 0.54, but there are lots of conflicts I need to resolve. It's definitely on my TODO list. That's also why I haven't really made a formal announcement yet.
Multithreaded DSP would have been much higher on my list than multi-channel,
Priorities are very subjective. Personally, I don't really think that multithreaded DSP has high priority for the general user base, as many patches seem to run fine on a single CPU. However, I do have projects that reach or exceed the limits of a single CPU - even on a beefy machine -, that's why I started working on this.
so I'm wondering if I could get away with using your tree as my basis for a while :)
Actually, it would be great to have some testers apart from myself!
Christof On 22.08.2023 10:32, Day Rush wrote:
How well does it work? It looks like the repo is based off of 0.52? Multithreaded DSP would have been much higher on my list than multi-channel, so I'm wondering if I could get away with using your tree as my basis for a while :)
- d
On Tue, 22 Aug 2023 at 01:17, Christof Ressi info@christofressi.com wrote:
To expand on Miller's reply:
Conceptually, messaging and DSP are two separate domains. Sending a message from a perform routine violates this separation. Instead you should use a clock with delay 0 to defer the message to the begin of the next scheduler tick.
Miller already mentioned the greatest danger, but there are other, more subtle issues. DSP objects typically operate on the premise that the object's state won't change from the outside during the perform routine. For example, imagine a delay object with a buffer that can be resized with a message; by sending a Pd message from the perform routine, it might accidentally feed back into the object and reallocate the buffer while still in progress.
Unfortunately, very little of this is documented. Ideally, this should be covered in the externals-how-to (https://github.com/pure-data/externals-howto); I just added an item on my (long) TODO list.
Finally, although Pd is currently single-threaded, this could change in the future. FWIW, here is a PoC for multi-threaded DSP: https://github.com/spacechild1/pure-data/tree/multi-threading. This is only possible because perform routines may only use a restricted set of API functions - which, in my fork, are annoted with the (empty) THREADSAFE macro (and made thread-safe, if necessary).
Christof
On 21.08.2023 20:55, Joseph Larralde wrote:
Hmm, I see ... unfortunately my random bug is totally unrelated to this weakness of my code. Thanks Miller for the explanation and pointers to examples ! And thanks Claude for the extra example. I'll check all my objects to see if there are other ones I can consolidate.
Cheers !
Joseph
Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit :
See bang~ in pure-data/src/d_misc.c for an example that uses a clock to send a message from DSP.
On 21/08/2023 18:02, Miller Puckette wrote:
The built-in objects "delay", "metro" and "pipe" use clocks in various ways.
On 8/21/23 18:02, Joseph Larralde wrote:
I just read in an answer from Christof to Alexandre : "never ever send a Pd message directly from a perform routine ! Always use a clock !"
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
-- GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Pd-dev mailing listPd-dev@lists.iem.athttps://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing listPd-dev@lists.iem.athttps://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing listPd-dev@lists.iem.athttps://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing listPd-dev@lists.iem.athttps://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
I actually get fewer xruns in callback mode,
This sounds highly unlikely. Maybe your "delay" setting is too low? Or Pd is not actually running with realtime priority?
I also bump the sound-generation process up to realtime priority.
Pd itself already tries to raise the thread priority; if this fails, you might not have sufficient permissions.
Christof
On 23.08.2023 22:55, Day Rush wrote:
For what it's worth, I actually get fewer xruns in callback mode, but I am running computation-heavy externals for much of my sound design so YMMV. I also bump the sound-generation process up to realtime priority.
On Wed, 23 Aug 2023 at 15:39, Joseph Larralde joseph.larralde@gmail.com wrote:
Wow, thanks again Christof, this greatly improves my understanding of Pd's engine. Indeed, I never use callback mode because everytime I did in the past I got some xruns, but had no clue about what was happening behind the scene. I feel a bit ashamed, I'm pretty sure I could have figured this out by reading more posts / docs / code ... I'm very grateful to both of you for taking the time to explain this in detail, and I hope this will benefit other users on the list. Best regards, Joseph Le 22/08/2023 à 17:22, Christof Ressi a écrit :
I've always been puzzled by the fact that everything runs on a single thread in Pd.
By default, Pd operates in "polling mode", i.e. the scheduler runs in its own thread (the main thread) and communicates with the audio callback via two lockfree ringbuffers (one for input, one for output). The size of the ringbuffers is set by the ominous "delay" parameter in the audio settings. The actual audio thread only reads/writes samples from/to the ringbuffers. If Pd operates in "callback mode" (= "callbacks" is ticked in the audio settings), the scheduler runs directly in the audio callback. You can save a little bit of latency, but it is less forgiving to CPU spikes or non-realtime-safe operations. Christof On 22.08.2023 15:08, Joseph Larralde wrote:
Thanks Christof for the additional insight. I've always been puzzled by the fact that everything runs on a single thread in Pd. I guess this single thread IS the audio thread because it processes audio, and I've always heard that one must never perform too many non-audio operations during an audio callback. But as you say, Pd runs fine for the general user base which I am part of. I'll probably give your version a try if I hit the limits with my current (rapidly growing) project running on a Pi 3 B+, but can't make any promises with my current schedule. Thanks for your work anyways. Best, Joseph Larralde -- freelance developer www.josephlarralde.fr <http://www.josephlarralde.fr> Le 22/08/2023 à 11:55, Christof Ressi a écrit :
How well does it work?
It seems to work quite well. With synthetic benchmarks I can get a 6x speedup on my 8 core machine, but I need to do some more practical testing and benchmarking.
It looks like the repo is based off of 0.52?
I think it's based on 0.53. I want to rebase it on 0.54, but there are lots of conflicts I need to resolve. It's definitely on my TODO list. That's also why I haven't really made a formal announcement yet.
Multithreaded DSP would have been much higher on my list than multi-channel,
Priorities are very subjective. Personally, I don't really think that multithreaded DSP has high priority for the general user base, as many patches seem to run fine on a single CPU. However, I do have projects that reach or exceed the limits of a single CPU - even on a beefy machine -, that's why I started working on this.
so I'm wondering if I could get away with using your tree as my basis for a while :)
Actually, it would be great to have some testers apart from myself! Christof On 22.08.2023 10:32, Day Rush wrote:
How well does it work? It looks like the repo is based off of 0.52? Multithreaded DSP would have been much higher on my list than multi-channel, so I'm wondering if I could get away with using your tree as my basis for a while :) - d On Tue, 22 Aug 2023 at 01:17, Christof Ressi <info@christofressi.com> wrote: To expand on Miller's reply: Conceptually, messaging and DSP are two separate domains. Sending a message from a perform routine violates this separation. Instead you should use a clock with delay 0 to defer the message to the begin of the next scheduler tick. Miller already mentioned the greatest danger, but there are other, more subtle issues. DSP objects typically operate on the premise that the object's state won't change from the outside during the perform routine. For example, imagine a delay object with a buffer that can be resized with a message; by sending a Pd message from the perform routine, it might accidentally feed back into the object and reallocate the buffer while still in progress. Unfortunately, very little of this is documented. Ideally, this should be covered in the externals-how-to (https://github.com/pure-data/externals-howto); I just added an item on my (long) TODO list. Finally, although Pd is currently single-threaded, this could change in the future. FWIW, here is a PoC for multi-threaded DSP: https://github.com/spacechild1/pure-data/tree/multi-threading. This is only possible because perform routines may only use a restricted set of API functions - which, in my fork, are annoted with the (empty) THREADSAFE macro (and made thread-safe, if necessary). Christof On 21.08.2023 20:55, Joseph Larralde wrote: > Hmm, I see ... unfortunately my random bug is totally unrelated to > this weakness of my code. > Thanks Miller for the explanation and pointers to examples ! > And thanks Claude for the extra example. > I'll check all my objects to see if there are other ones I can > consolidate. > > Cheers ! > > Joseph > > Le 21/08/2023 à 19:08, Claude Heiland-Allen a écrit : >> See bang~ in pure-data/src/d_misc.c for an example that uses a clock >> to send a message from DSP. >> >> On 21/08/2023 18:02, Miller Puckette wrote: >>> The built-in objects "delay", "metro" and "pipe" use clocks in >>> various ways. >>> >>> On 8/21/23 18:02, Joseph Larralde wrote: >>>> I just read in an answer from Christof to Alexandre : "never ever >>>> send a Pd message directly from a perform routine ! Always use a >>>> clock !" >> >> >> >> >> _______________________________________________ >> Pd-dev mailing list >> Pd-dev@lists.iem.at >> https://lists.puredata.info/listinfo/pd-dev > > > > > _______________________________________________ > Pd-dev mailing list > Pd-dev@lists.iem.at > https://lists.puredata.info/listinfo/pd-dev _______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev -- GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt _______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
_______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
_______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
_______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
_______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
-- GPG Public key at http://cyber-rush.org/drr/gpg-public-key.txt
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
On Wed, 23 Aug 2023 at 23:24, Christof Ressi info@christofressi.com wrote:
I actually get fewer xruns in callback mode,
This sounds highly unlikely. Maybe your "delay" setting is too low? Or Pd is not actually running with realtime priority?
I spent a lot of time testing this on an ancient laptop running a fairly modern kernel because I was deeply frustrated with general PD performance on that machine. "unlikely" it may have been. True, it most certainly was.
I also bump the sound-generation process up to realtime priority.
Pd itself already tries to raise the thread priority; if this fails, you might not have sufficient permissions.
Perhaps. But I was definitely able to manually bump the priority without sudo. I did a *lot* of system optimization trying to squeeze good performance out of various moderately complicated physical models. From this I learned a few things:
1 - the PD UI will absolutely kill performance 2 - because of 1, plan to run the sound gen in [pd~] 3 - pd patch and file lookup is a nightmare, especially in [pd~] 4 - real-time priority + callbacks usually produces clean sound on a clean system
And now you know why I want multi-threaded pd audio.
- d
Perhaps. But I was definitely able to manually bump the priority without sudo.
I don't doubt that you can manually bump the priority; that doesn't necessarily mean that Pd itself can do it.
BTW, if Pd fails to raise the thread priority to RT, you should get the following error message in the Pd console:
"priority %d scheduling failed; running at normal priority"
1 - the PD UI will absolutely kill performance
The Pd GUI runs as a separate process with lower priority. If you mean the actual network I/O for core <-> GUI communication, then I don't see how running Pd in callback mode would improve this - on the contrary!
If GUI network I/O really is a problem in your patches, then https://github.com/pure-data/pure-data/pull/1261 would be a proper solution.
2 - because of 1, plan to run the sound gen in [pd~]
The parent and child processes communicate via pipes, which is very similar to how the scheduler and audio callback communicate in polling mode. I'm pretty sure that the overall effect is the same.
NB: the default buffersize for [pd~] is 5 blocks (6.6 ms @ 48 kHz).
In general, it doesn't really make sense to run *all* DSP in [pd~]; instead, just use the standard polling mode and raise "delay" accordingly.
If you are really unable to get a clean signal in polling mode, even with high "delay" settings, please file a bug report at GitHub. It may very well be an issue with your computer/OS. Did you try other machines?
BTW, you might also try my scheduler updates which, among other things, improves the responsiveness of the scheduler in polling mode: https://github.com/pure-data/pure-data/pull/1756
And now you know why I want multi-threaded pd audio.
I definitely appreciate the interest :) but I think that multi-threaded DSP is really orthogonal to the problem you have described in your last e-mail.
Christof
On 24.08.2023 14:14, Day Rush wrote:
On Wed, 23 Aug 2023 at 23:24, Christof Ressi info@christofressi.com wrote:
I actually get fewer xruns in callback mode,
This sounds highly unlikely. Maybe your "delay" setting is too low? Or Pd is not actually running with realtime priority?
I spent a lot of time testing this on an ancient laptop running a fairly modern kernel because I was deeply frustrated with general PD performance on that machine. "unlikely" it may have been. True, it most certainly was.
I also bump the sound-generation process up to realtime priority.
Pd itself already tries to raise the thread priority; if this fails, you might not have sufficient permissions.
Perhaps. But I was definitely able to manually bump the priority without sudo. I did a *lot* of system optimization trying to squeeze good performance out of various moderately complicated physical models. From this I learned a few things:
1 - the PD UI will absolutely kill performance 2 - because of 1, plan to run the sound gen in [pd~] 3 - pd patch and file lookup is a nightmare, especially in [pd~] 4 - real-time priority + callbacks usually produces clean sound on a clean system
And now you know why I want multi-threaded pd audio.
- d
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
On Thu, 24 Aug 2023 at 14:12, Christof Ressi info@christofressi.com wrote:
Perhaps. But I was definitely able to manually bump the priority without sudo.
I don't doubt that you can manually bump the priority; that doesn't necessarily mean that Pd itself can do it.
BTW, if Pd fails to raise the thread priority to RT, you should get the following error message in the Pd console:
"priority %d scheduling failed; running at normal priority"
I don't recall seeing that on the console, but I may have seen it on stdout once or twice.
1 - the PD UI will absolutely kill performance
The Pd GUI runs as a separate process with lower priority. If you mean the actual network I/O for core <-> GUI communication, then I don't see how running Pd in callback mode would improve this - on the contrary!
This has nothing to do with callback mode, as such. it is a general performance note included to illustrate the various things that I discovered, often with much debugging of PD itself, which affect performance.
2 - because of 1, plan to run the sound gen in [pd~]
In general, it doesn't really make sense to run *all* DSP in [pd~]; instead, just use the standard polling mode and raise "delay" accordingly.
This is a very disappointing answer. I really keep hoping to get away from static composition and move towards live performance, and yet you tell me that the main remedy is to increase lag? Is PD really just CSound with a better sound design workflow?
It may very well be an issue with your computer/OS. Did you try other machines?
As I said earlier, it was quite an old laptop, and the composition had a lot of physically modelled voices. My Win laptop was unilaterally upgraded to Win11 by u$oft and ceased to perform well at anything other than playing video, so I kind of left it behind. The list I provided gave me nice clean sound. The most effective single change was the change to [pd~]. I will freely grant the possibility that the re-architecture of my program necessary to run in that environment may have improved performance, but that still points to UI (and the attendant clunky communication) issues as being a primary performance problem. Running the audio DSP in an execution context separate from UI messaging seems to me to be a crucial performance improvement for PD. My experience with [pd~] certainly shows that. I would hope that a separately threaded DSP engine would do the same.
This has nothing to do with callback mode, as such. it is a general performance note included to illustrate the various things that I discovered, often with much debugging of PD itself, which affect performance.
Ok, I see. Note that *receiving* messages is more or less fine because the I/O happens with select() and therefore essentially non-blocking. The problem is *sending* messages. The proper solution is to move network I/O to a dedicated thread (https://github.com/pure-data/pure-data/pull/1261), but I guess one could mitigate the problem by increasing the socket send buffer size, so that send() is less likely to block.
--
yet you tell me that the main remedy is to increase lag?
The main remedy is to get a better computer :) Most importantly, a CPU with strong single-thread performance and good ventilation to prevent throttling. Also, make sure to set the energy manager to highest performance.
Many users (including myself) manage to run Pd with latencies below 10ms - which I would consider suitable for live performance. I was mainly questioning your claim that you cannot get a clean output with the polling mode *at all*.
That being said, the current polling mode implementation *does* have a few problems - which I am trying to address with https://github.com/pure-data/pure-data/pull/1756.
--
The most effective single change was the change to [pd~]
Again, this just adds another layer of buffering. I am not surprised that you see more stable performance, but you should get the same effect with the polling scheduler. Please try my scheduler-fix branch above!
--
Running the audio DSP in an execution context separate from UI messaging seems to me to be a crucial performance improvement for PD. My experience with [pd~] certainly shows that. I would hope that a separately threaded DSP engine would do the same.
Multi-threaded DSP only lets you distribute the *DSP* CPU load over several cores. It does not affect CPU spikes caused by messaging or I/O operations. While the latter *can* be moved to dedicated threads, Pd messages always execute in the same thread as DSP by design; multi-threaded DSP does not change that. The idea of the polling scheduler is that you add some additional buffering to "absorb" CPU spikes caused by the messaging system. The required delay really depends on the patch in question and the system in general.
Now, you *can* also use the callback scheduler with a large enough "block size" (= hardware buffer size) instead, but you are limited to power-of-two values. For example, if 512 samples just does not cut it, you are forced to move to 1024; there is no room in between. With the polling scheduler, however, you can set the delay at a much finer granularity. Typically, you would set the "block size" to the lowest possible value (with a good machine and audio interface, 64 samples should be possible), and then adjust the "delay" as necessary.
Christof
On 24.08.2023 16:48, Day Rush wrote:
On Thu, 24 Aug 2023 at 14:12, Christof Ressi info@christofressi.com wrote:
Perhaps. But I was definitely able to manually bump the priority without sudo.
I don't doubt that you can manually bump the priority; that doesn't necessarily mean that Pd itself can do it. BTW, if Pd fails to raise the thread priority to RT, you should get the following error message in the Pd console: "priority %d scheduling failed; running at normal priority"
I don't recall seeing that on the console, but I may have seen it on stdout once or twice.
1 - the PD UI will absolutely kill performance
The Pd GUI runs as a separate process with lower priority. If you mean the actual network I/O for core <-> GUI communication, then I don't see how running Pd in callback mode would improve this - on the contrary!
This has nothing to do with callback mode, as such. it is a general performance note included to illustrate the various things that I discovered, often with much debugging of PD itself, which affect performance.
2 - because of 1, plan to run the sound gen in [pd~]
In general, it doesn't really make sense to run *all* DSP in [pd~]; instead, just use the standard polling mode and raise "delay" accordingly.
This is a very disappointing answer. I really keep hoping to get away from static composition and move towards live performance, and yet you tell me that the main remedy is to increase lag? Is PD really just CSound with a better sound design workflow?
It may very well be an issue with your computer/OS. Did you try other machines?
As I said earlier, it was quite an old laptop, and the composition had a lot of physically modelled voices. My Win laptop was unilaterally upgraded to Win11 by u$oft and ceased to perform well at anything other than playing video, so I kind of left it behind. The list I provided gave me nice clean sound. The most effective single change was the change to [pd~]. I will freely grant the possibility that the re-architecture of my program necessary to run in that environment may have improved performance, but that still points to UI (and the attendant clunky communication) issues as being a primary performance problem. Running the audio DSP in an execution context separate from UI messaging seems to me to be a crucial performance improvement for PD. My experience with [pd~] certainly shows that. I would hope that a separately threaded DSP engine would do the same.
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev