refactoring PureUGen as a class method

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

refactoring PureUGen as a class method

Nathan Ho
hi list,

at https://github.com/supercollider/supercollider/issues/3371 we are
discussing inconsistent usage of the PureUGen abstract class, and a
potential refactor came up. there's an agreement that ugen purity may be
better indicated with a class method rather than an inheritance tree
property.

as a suggestion, we could call this method "hasNoSideEffects" to be more
explicit about the meaning of ugen purity. the downsides are few:
backward compatibility can be easily maintained with e.g. "PureUGen {
*hasNoSideEffects { ^true } }".

any thoughts?


nathan

_______________________________________________
sc-dev mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-dev/
search: http://www.listarc.bham.ac.uk/lists/sc-dev/search/
Reply | Threaded
Open this post in threaded view
|

Re: refactoring PureUGen as a class method

julian.rohrhuber

> On 01.01.2018, at 18:44, [hidden email] wrote:
>
> hi list,
>
> at https://github.com/supercollider/supercollider/issues/3371 we are discussing inconsistent usage of the PureUGen abstract class, and a potential refactor came up. there's an agreement that ugen purity may be better indicated with a class method rather than an inheritance tree property.
>
> as a suggestion, we could call this method "hasNoSideEffects" to be more explicit about the meaning of ugen purity. the downsides are few: backward compatibility can be easily maintained with e.g. "PureUGen { *hasNoSideEffects { ^true } }".
>
> any thoughts?


maybe the expression “side effect” is a little misleading. Take for example an Out ugen: the “side effect” is exactly the effect. Similar with FreeSelf. But I really agree that it is better not to base behaviour on subclassing here, but on a simple attribute.

Somehow, “isPure”, or “isPureUGen" convey it better.







signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: refactoring PureUGen as a class method

brianlheim
I think "pure" makes the most sense as terminology. This is a well-defined term (as in "pure function") that describes the concept that the name PureUGen is meant to convey - no side effects, computation is only based on inputs.

Following that train of thought, James asked a question about whether using shared RNGs makes a UGen impure. It clearly does based on the definition of a pure function, but in the context where it will be used it doesn't seem to matter IIUC. If there is some possibility at all that in the future it could be desirable to be able to reproduce behavior of a fixed RNG seed, then it seems like it would be better to be conservative and stick to the strict definition. Or perhaps offer a "usesSharedRNG" property as well.

-Brian

On Mon, Jan 1, 2018 at 3:30 PM, <[hidden email]> wrote:

> On 01.01.2018, at 18:44, [hidden email] wrote:
>
> hi list,
>
> at https://github.com/supercollider/supercollider/issues/3371 we are discussing inconsistent usage of the PureUGen abstract class, and a potential refactor came up. there's an agreement that ugen purity may be better indicated with a class method rather than an inheritance tree property.
>
> as a suggestion, we could call this method "hasNoSideEffects" to be more explicit about the meaning of ugen purity. the downsides are few: backward compatibility can be easily maintained with e.g. "PureUGen { *hasNoSideEffects { ^true } }".
>
> any thoughts?


maybe the expression “side effect” is a little misleading. Take for example an Out ugen: the “side effect” is exactly the effect. Similar with FreeSelf. But I really agree that it is better not to base behaviour on subclassing here, but on a simple attribute.

Somehow, “isPure”, or “isPureUGen" convey it better.







Reply | Threaded
Open this post in threaded view
|

Re: refactoring PureUGen as a class method

julian.rohrhuber


> On 01.01.2018, at 21:53, [hidden email] wrote:
>  If there is some possibility at all that in the future it could be desirable to be able to reproduce behavior of a fixed RNG seed, then it seems like it would be better to be conservative and stick to the strict definition. Or perhaps offer a "usesSharedRNG" property as well.

Yes, it will certainly affect the behaviour when the noise ugens are used together with a RandSeed UGen.

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: refactoring PureUGen as a class method

jamshark70-2
In reply to this post by brianlheim

On January 2, 2018 4:54:39 AM [hidden email] wrote:

> I think "pure" makes the most sense as terminology. This is a well-defined
> term (as in "pure function") that describes the concept that the name
> PureUGen is meant to convey - no side effects, computation is only based on
> inputs.


Based only on inputs *and* the only thing that matters is the function's output (the function alters nothing outside of its internal scope, apart from providing an output).

Julian:
> Take for example an Out ugen: the “side effect” is exactly the effect.

But it is still a side effect: Out's output is meaningless and normally discarded. It doesn't matter if the side effect is the main effect: it's a change in the state of the system other than the unit's direct output. I think we can use the formal term here.

Brian again:


> Following that train of thought, James asked a question about whether using
> shared RNGs makes a UGen impure. It clearly does based on the definition of
> a pure function, but in the context where it will be used it doesn't seem
> to matter IIUC. If there is some possibility at all that in the future it
> could be desirable to be able to reproduce behavior of a fixed RNG seed,
> then it seems like it would be better to be conservative and stick to the
> strict definition.

Formally, yes, RNG-consumers do alter the state of the system apart from their direct output.

But consider where this matters. The distinction is important mainly (only?) for dead code elimination. If a chain of pure UGens never plugs into a nonpure UGen somewhere, then the pure UGens' impact (direct output) is lost and these UGens may be deleted. For this to make a difference to RNGs, a user would have to add a random/noise UGen *only* for the purpose of tweaking the RNGs state and never connect it to anything else. It's a highly implausible scenario. The whole point of an RNG is that localized movement from one value to the next should overwhelm any systematic patterns in the output. Any difference between the series r0, r1, r2, r3, r4, r5 and the series r0, r1, r2, r4, r5 should be imperceptible in the long run, or it's a bad RNG.

Again, it's not impossible that some user might be doing this... but the argument could also be made that it's a bit of a folly to count on a random number generator for that level of deterministic specificity. OTOH, asking modern general-purpose operating systems to produce real-time audio with imperceptible latency is also a bit of a folly, so... we're already doing weird things.

A workaround, btw, might be Out.ar(out, rng + sig - rng) -- math optimizations aren't smart enough to cancel the two rng terms in that expression.

hjh

Sent with AquaMail for Android
http://www.aqua-mail.com

Reply | Threaded
Open this post in threaded view
|

Re: refactoring PureUGen as a class method

brianlheim

> > I think "pure" makes the most sense as terminology. This is a well-defined
> > term (as in "pure function") that describes the concept that the name
> > PureUGen is meant to convey - no side effects, computation is only based on
> > inputs.

> Based only on inputs *and* the only thing that matters is the function's output (the function alters nothing outside of its internal
> scope, apart from providing an output).

Yes, that would be the "no side effects" part ...

> For this to make a difference to RNGs, a user would have to add a random/noise UGen *only* for the purpose of tweaking the
> RNGs state and never connect it to anything else. It's a highly implausible scenario.

Or, there could be accidental dead code due to mistakes while changing a UGen graph. If at that point the user hardcodes a seed they like, we're breaking backwards compatibility for that user. Another possibility is that the user begins with 8 RNG UGens that control parameters elsewhere in the graph, and chooses a hardcoded seed. Later, they decide one of the parameters is irrelevant and hardcode its value rather than using the RNG input. Now there's supposedly dead code that can't be removed without losing the originally chosen sequence.

> Any difference between the series r0, r1, r2, r3, r4, r5 and the series r0, r1, r2, r4, r5 should be imperceptible in the long run, or it's a bad RNG.

But it could be very perceptible in the short run. Perhaps this is the set of numbers that feeds into a larger musical structure, like a repeated melody or duration series.

I'm not wholly convinced by the scenarios I just gave. They also seem quite rare. But then again, the potential speed gain from eliminating dead RNG UGens seems pretty infrequent as well. At this point I'd probably still opt for the conservative approach, which can always be made more aggressive in the future.

-Brian

On Mon, Jan 1, 2018 at 7:36 PM, <[hidden email]> wrote:

On January 2, 2018 4:54:39 AM [hidden email] wrote:

> I think "pure" makes the most sense as terminology. This is a well-defined
> term (as in "pure function") that describes the concept that the name
> PureUGen is meant to convey - no side effects, computation is only based on
> inputs.


Based only on inputs *and* the only thing that matters is the function's output (the function alters nothing outside of its internal scope, apart from providing an output).

Julian:
> Take for example an Out ugen: the “side effect” is exactly the effect.

But it is still a side effect: Out's output is meaningless and normally discarded. It doesn't matter if the side effect is the main effect: it's a change in the state of the system other than the unit's direct output. I think we can use the formal term here.

Brian again:


> Following that train of thought, James asked a question about whether using
> shared RNGs makes a UGen impure. It clearly does based on the definition of
> a pure function, but in the context where it will be used it doesn't seem
> to matter IIUC. If there is some possibility at all that in the future it
> could be desirable to be able to reproduce behavior of a fixed RNG seed,
> then it seems like it would be better to be conservative and stick to the
> strict definition.

Formally, yes, RNG-consumers do alter the state of the system apart from their direct output.

But consider where this matters. The distinction is important mainly (only?) for dead code elimination. If a chain of pure UGens never plugs into a nonpure UGen somewhere, then the pure UGens' impact (direct output) is lost and these UGens may be deleted. For this to make a difference to RNGs, a user would have to add a random/noise UGen *only* for the purpose of tweaking the RNGs state and never connect it to anything else. It's a highly implausible scenario. The whole point of an RNG is that localized movement from one value to the next should overwhelm any systematic patterns in the output. Any difference between the series r0, r1, r2, r3, r4, r5 and the series r0, r1, r2, r4, r5 should be imperceptible in the long run, or it's a bad RNG.

Again, it's not impossible that some user might be doing this... but the argument could also be made that it's a bit of a folly to count on a random number generator for that level of deterministic specificity. OTOH, asking modern general-purpose operating systems to produce real-time audio with imperceptible latency is also a bit of a folly, so... we're already doing weird things.

A workaround, btw, might be Out.ar(out, rng + sig - rng) -- math optimizations aren't smart enough to cancel the two rng terms in that expression.

hjh

Sent with AquaMail for Android
http://www.aqua-mail.com


Reply | Threaded
Open this post in threaded view
|

Re: refactoring PureUGen as a class method

jamshark70-2

On January 2, 2018 9:55:41 AM [hidden email] wrote:

> I'm not wholly convinced by the scenarios I just gave. They also seem quite
> rare. But then again, the potential speed gain from eliminating dead RNG
> UGens seems pretty infrequent as well. At this point I'd probably still opt
> for the conservative approach, which can always be made more aggressive in
> the future.


I'd be happy with that (the conservative approach) -- as a deliberate decision such as we're making here, rather than the current situation: "we introduced the concept of a PureUGen but then forgot to use it in a lot of places where it's appropriate" ;-p

hjh

Sent with AquaMail for Android
http://www.aqua-mail.com

Reply | Threaded
Open this post in threaded view
|

Re: refactoring PureUGen as a class method

brianlheim
> as a deliberate decision such as we're making here, rather than the current situation: "we introduced the concept of a PureUGen > but then forgot to use it in a lot of places where it's appropriate" ;-p

:) I think that sounds good. Either way, I'm glad someone is working on this.

-Brian

On Mon, Jan 1, 2018 at 10:11 PM, <[hidden email]> wrote:

On January 2, 2018 9:55:41 AM [hidden email] wrote:

> I'm not wholly convinced by the scenarios I just gave. They also seem quite
> rare. But then again, the potential speed gain from eliminating dead RNG
> UGens seems pretty infrequent as well. At this point I'd probably still opt
> for the conservative approach, which can always be made more aggressive in
> the future.


I'd be happy with that (the conservative approach) -- as a deliberate decision such as we're making here, rather than the current situation: "we introduced the concept of a PureUGen but then forgot to use it in a lot of places where it's appropriate" ;-p

hjh

Sent with AquaMail for Android
http://www.aqua-mail.com