efficiency comparison between objects...

Julien Bayle's icon

I'd like to know more about quantitative comparison

For example, I can use [zmap] object to map min/max from a range to another.
I can also use an expression object [expr].

what is the best to use ?
even if we can measure things, I talk about developers point of view.

Is there a rule about that?
A rule like: "using expr everywhere we can instead of other things cause it is more efficient" etc etc

I hope I'm not the only one interested by that ;)

Julien Bayle's icon

I guess you're right about expr, raja.
It depends of what it is inside expr.

zmap 0 127 0. .85 & expr( ($i1 /127) *.85 ) are equivalent.
The formula is light, I guess the difference isn't very big.

But generally, as you said, using a dedicated object for the task could be my rule :)

Julien Bayle's icon

hello vanille,
indeed, it is a nice object!
I'm looking for the post right now :)

Bas van der Graaff's icon

For most of the objects you have a general idea of how fast they operate, but of course you're not always right. Would be nice to have a list of speeds for various objects (with various input).

Sprintf will always be slower, but you cannot edit strings with [prepend] or [append]. I'd always choose [prepend] or [zl join] over string operations whenever possible, but I'd like to know the exact difference in speed as well...

Julien Bayle's icon

It is hard to find that.
Andrew? any idea? (not sure Andrew reads this thread but ..)

Peter Castine's icon

Efficiency rule #1: Don't worry about efficiency unless you have to.

Worrying about patch efficiency when your patch is fast enough anyway is a wasteful use of another, far more valuable resource: your own time and energy.

That said, experienced patchers will follow a couple of rules of thumb:

- In general, prefer to use a single object rather than a group of objects

- In general, prefer non-GUI objects to GUI objects (if you don't need the GUI paraphenalia)

- In general, prefer a dedicated object for a specific task rather than a more general purpose object (scale or zmap or lp.scampf rather than expr; similarly mtof rather than expr).

A side-effect of the last RoT is that you may get slightly higher accuracy with dedicated objects like mtof. The internal calculations will almost always be performed with 64-bit floating point. I'm not sure, but expr may be truncating intermediary calculations to 32-bit. You'll certainly have 32-bit intermediary results if you implement the same formula by patching together a series of Max arithmetic objects.

But far more important than the CPU demands of individual objects is an efficient patch design. Worrying about zmap vs. expr is generally a sign that you're barking up the wrong tree.

Julien Bayle's icon

hello,
thanks a lot for your comments/ideas/opinions

Peter, I agree 100%
"Efficiency rule #1: Don't worry about efficiency unless you have to.

Worrying about patch efficiency when your patch is fast enough anyway is a wasteful use of another, far more valuable resource: your own time and energy."

I'm sure my patch lag a bit in 2 particular point, so, indeed, in this case, I'm sure it isn't a waste of time. But you're right for all the other cases :)

About the design.
I'd love to get my patch read by another person.
I have a lot of question about it. But it is often other people learning too, so a nice person a little bit more experts that could read it would be great.
indeed, I cut my patch in a lot of sub-patch in order to organize things a bit.
perhaps, it isn't a nice interface designing strategy.
I asked these questions on ableton forums:
- http://forum.ableton.com/viewtopic.php?f=1&t=131229
- http://forum.ableton.com/viewtopic.php?f=1&t=130802
I quoted it in order to show my kind of questions.

I optimized a bit these days.
I'm sure I could do better.
all the best

cudnylon's icon

We should all get together and make a thread with efficiency examples then sticky it to the top of the forum. Show the bad way and the better way to do things. That and a step-sequencer tutorial. Those seem to be the two main questions that always show up.

Julien Bayle's icon

I began several tests in order to optimize my patch.
I'll post those on my website asap.

AlexHarker's icon

Peter's comments are I think an excellent starting point for thinking about efficiency when coding - code first and (if you need to) optimise later.

However, for the times when optimisation is necessary I think the key idea is:

Benchmark - find and work on the part of your code that is slowest first.

By this I mean:

Imagine you have 6 subpatchers chained together, you time them and find that one of them takes 50% of the time, whilst the other 5 share the other 50% taking 10% each. From this we can see that a speed up of twice as fast for one of the less CPU intensive subpatchers will result in a gain of 5% overall. The same speed up for the more intensive subpatcher would gain 25% overall - so it's a much better use of your time to optimise the most CPU intensive part of your process than the bits which are taking up less time.

Likewise it is rarely worth optimising one off calculations or processes (like file loading) unless they are a perceivable issue, because you don't get any real performance gain from this.

And I'd also echo Peter's comment about patch design and algorithm choice really being a much more common issue than choice of objects (with far bigger gains achievable and hence a better investment of your time). However, again, you can only really work this out by benchmarking real situations. You're driving hundreds of zmaps/exprs at a rate of once each 3 ms? - well you might care more in this situation than when you have one object that gets sent a number every 2 seconds or so - the key thing is to break up your patch into bits and find out where you're spending the time - if that gets down to the level of individual objects so be it, but unless you know how much of your CPU you are spending where you're likely to waste a lot of time and energy.

Regards

Alex

Julien Bayle's icon

Alex, if you tell me how I can measure that, I'd be happy :)

AlexHarker's icon

@julien/protofuse:

Aas vanille's patch - uzi and cpuclock - you'll have to figure out what messages to send - try a whole chain first - then break it into bits until you find where the problem is (if there's a problem). Basically the idea is to set your uzi large enough so that the values are significant (maybe between a few ms and a few hundred ms).

If your total time is 100ms for a message then you know that if part of that chain is 10ms that's 10% etc, etc, Unfortunately there is no easy way to do this. It's a lot of manual effort and re-patching to measure the various bits - and you'll also have to work out what are sensible bits....

In the case of your questions on the other forum I'd say make a patch that generates random midi data when you bang it (correctly formatted but representative of what might be coming in) - bang that with the uzi - time the result, but make sure you subtract the cost of the generation subpatch.

Max Patch
Copy patch and select New From Clipboard in Max.

Also - yes sends and receives are slower than patch cords - but I'd supsect you would need A LOT of data, or a lot of sends and receives to notice it in real terms) - Here's a patch that shows the difference:

@raja - real times are helpful when looking at real-life situations, but I'd say it's more helpful to think in percentages - the timings that the patch is giving are arbitrary anyway - want bigger ones? Make the number in the uzi boxes bigger - smaller ones? - do the opposite. If the timings you're getting relate to a real life scenario that might be useful (1 ms may be fine in one scenario not in another) - for more general purposes percentages give you an idea of how much faster/slower one approach is to another)

Hope that helps

Alex

Julien Bayle's icon

I put a lot of informations there: http://www.julienbayle.net/diy/protodeck/#m4L

I'll update with last patch asap (today)

I derived a bit from my real first purpose: find the best architecture for my patch, to make it the most efficient.
so I agree that measures are only useful in real conditions...

Alex, would you take a moment to "read" my patch?
I can guide you a bit via chat (msn or whatever you want)

all the best, and thanks a lot for all these words :)

Julien Bayle's icon

the bottleneck is the way I use to update my hardware led matrix.
especially the concept under the hood.

I store clips ID in a coll.
I store clips coordinates in the index of this coll.
The index is coded like that: track number * 100 + clip_slot number.

So I have a big coll, filled at the beginning of the set.

I have a 6x8 grid on the hardware. 6x8 = 1 "song"
So at each instant, there is a current song index, and my 6x8 is a kind of little windows moving up and down in the coll value.

at each instant, I only need 48 IDs for my observer/objects stuff.
So I fire all the index I need to the coll, and this coll answers with the clips ID to a big matrix of observer/objects.

I knew it would be THE bottleneck.
At least when I change the current song (all 48 IDs requested) ; because in a song, all update on triggering, playing, stopping are VERY fast.
So it is correct.

But I'd like to correct my way a bit, cause I'm sure I could do better.

I did that: http://www.julienbayle.net/public/THEbottleneck.jpg
the mean time is around 1s. for some people it would be awful, for me it could be correct.

Could someone help me?

The bottleneck is on the patch I sent a snapshot, or inside the matrix.
I guess I can improve the routing stuff part!
The matrix is this one : http://www.julienbayle.net/public/matrixProtodeck.jpg

And the smallest elements are: ledunit
http://www.julienbayle.net/public/ledUnit2.jpg

if someone could help me, it would be very great for the knowledge of forum reader, for my patch etc :)