Max, poly~ and parallel processing

Then I would need to change all my namespace (sends, receives and buffer names), as those are shared across top level patches. I tried with #0, but ran into some other issues.

What is the analysis that is taking long for you, or is it that there is lots and lots of files to analyse?

I’m building the most exhaustive database possible with pretty much all known descriptors, mfcc, melbands and their derivatives on large quantities of sounds. This will facilitate quick switching between them when comparing the dataset inputs.

1 Like

to reiterate the point @weefuzzy made: our buffer objects spawn their own thread, and do one task at a time, so having 4 jobs in parallel in the same patch (4 bufnmf for instance) is the same as having them on 4 different patchers at top level…

Having a poly~ to do that is just good to keep the upscaling easy to explore (changing the number of instances) but would have no difference than to load X abstractions sideways in a single patch.

p

To be explicit: this is when @blocking 0 is set. Otherwise everything will queue in the main thread.

Running large batches is continuously increasing memory usage of the patch (or the compiled app). I’m making sure that all buffers (sound, temp, stats etc.) receive a samps 1 1 message before replacing the main analysis buffer with the next sound. Do you have a good method to track the portion of the patch which is the culprit?

I remember you mentioning something about runaway memory aaages ago. Is that right?

I tend to resort to specialised developer tools at that point, because when all you have is a hammer, etc. I’m not aware of anything usefully granular outside of the toys that come with Xcode. @a.harker do you have any hot tips?

In any case, @tutschku, if this is broadly the same patch you shared in the Mfcc comparison thread I can try running it a bunch of times with the debugger attached and see what I see.

There was a memory leak in alpha 7, but I’m pretty sure we fixed that :grin:

This is the latest version. Just follow the index numbers to get it going.
1 this is the ‘base’ folder, the one where all other sound folders need to be located
2 drop any number of folders here (they can be from deeper folder levels - as long as they are in the base folder
3+4 assembling lists for the looping
5 start

unzip and put into Projects folder

Folders-to-database-34.zip (314.5 KB)

I’m getting some js errors at startup, did not worry about it yet, as the patch is functioning.

The analysis database files (one per folder) are written into a time-stamped folder inside patchers

Cheers. Do you know offhand roughly how big your corpus is, and what sort of memory usage you’re seeing it build up to? (Just ballparks - will help tracing hypotheical causes…)

one test was on 11k sounds, memory grew to 3.8 gb

That doesn’t seem too bad.

Is it loading a single sample, analyzing it, clearing it, then loading another one etc…?

Or is it doing that concatenation thing that @tremblap’s patch does and then analyzing a single “long flat” buffer?

No concatenation. One file is analyzed after the other. When I open the patch Max uses about 600mb. From there on the memory is steadily growing. I needed to kill it at some point as it got extremely slow, using swap memory on the disk. There is some object or my bad programming not releasing memory correctly.

Instruments can be used to trace memory allocations.

I had a first quick look yesterday evening. The good news is that there isn’t an obvious memory leak where the heap is just getting bigger and bigger on successive analyses. I haven’t yet tested against an especially large set because I have to use un-optimised builds for this, which makes everything verrry sloooow.

If you’re expecting to see the reported usage go down after an analysis, this is unlikey to happen, because released memory isn’t (normally / often) handed straight back to the operating system, but remains in the application’s free list against future allocations. This is all low level stuff that we don’t control.

However, there is scope to lower the memory footprint for your patch, which might well help. FluidBufMFCC uses quite a lot of memory internally because it needs to maintain a matrix of stuff big enough to cope with its maximum FFT size. Given that your FFT size is fixed, changing your boxes to specify 4096 as a maximum up front should help:
[fluid.bufmfcc~ 4096 @source htsound @features fluid_mfcc @numcoeffs 20 @fftsettings 4096 2048 4096]

Interesting. I didn’t know this.

So would this also “speed things up” some? For the patch I was working on the hybrid splitting thread I kept massaging settings to eek out every bit of speed I could as it’s doing loads of stuff in a tiny time frame, and given that I often use a Max fft size of 512, wondering if it would benefit to specify that up front.

It’s highly unlikely. This memory is allocated once per box and then stays where it is until the box is destroyed. So, unless you’e suffering from lots of swapping (and even then), it’s neither here nor there for processing speed purposes.

As a general principle, if you’re looking to make your stuff lean then capping the max sizes (mostly FFT, but not only) to stuff you’re sure you’ll never want to exeed will trim things down memory wise, but only with a secondary effect on performance, at best.

Somewhere on my and @tremblap’s mañana list is to fix things up for offline objects so that Max<X> arguments are strapped to @X attribute if the argument isn’t supplied. This is primiarily to deal with the annoyance of the buffers for things like BufMFCC being bigger than one would expect, but would also (I think) make for less surprise here.

That sounds about right. I didn’t know about this, so I was worried I was “leaving cash on the table” with a small tweak.

I’m not really running into memory issues (yet), but that will start to become a bit of an issue with these larger multi-channel decomposed buffers. Tying the two together is a good idea I think.