Performance issues with libROSA

678 views
Skip to first unread message

Stephen Etheridge

unread,
Mar 2, 2015, 9:53:24 AM3/2/15
to lib...@googlegroups.com

I am using libROSA from Python 2.7 to detect the BPM of a set of audio tracks.

The first time I ran my script it happily detected the beats of 243 tracks then stopped, i.e. it sat on the 244th track for hours and I aborted the run. Now, every time I run the same script again it will do the first track in the list (a different one as I increment between each run) quite happily then performance goes downhill very quickly, i.e. it basically stops. I am using a Lenovo T540p with 16GB RAM on Fedora 20. I have "googled" for librosa and performance and have got no results so any insights you have would be gratefully received. "$ ps -ef" whilst the process seems to have hanged gives a large number of "kworker" processes which I do not normally see, so I suspect there needs to be a way of "cleaning" things out after every call to librosa but I am not sure how to do that.

Any help would be gratefully received. 

Brian McFee

unread,
Mar 2, 2015, 10:16:55 AM3/2/15
to lib...@googlegroups.com
Hi Stephen,

A few questions about your setup:

1) what are your dependency versions?  (numpy, scipy, etc)

2) do you have scikits.samplerate installed?

3) what are your beat tracking parameters?

4) are you running the entire loop in python, or spinning a new python instance for each track?

5) is there something special about track 244?  Is it much longer than the others?

Stephen Etheridge

unread,
Mar 3, 2015, 2:03:23 AM3/3/15
to lib...@googlegroups.com
Hi Brian,
Answers in line, but I think no. 4 points to the issue:


A few questions about your setup:

1) what are your dependency versions?  (numpy, scipy, etc)

numpy==1.8.2
scikit-learn==0.14.1
scipy==0.15.1

2) do you have scikits.samplerate installed?
No, it would not load so I get a message about falling back to scipy.signal

3) what are your beat tracking parameters?
Not sure what this means, I have "stolen" the example from the tutorial, i.e.

hop_length=64
...
y,sr=librosa.load(filename)
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr, hop_length=hop_length)


4) are you running the entire loop in python, or spinning a new python instance for each track?
I was running the entire loop in python and I think this is where the issue is.  I have now written a python script which accepts the name of a track and only does BPM detection on that track and then shuts down.  I have written a wrapper around that to feed filenames in and that seems to work ok now without spawning the myriad [kworker] processes I was seeing and performance is fine.  To use a java expression, I wonder if, for the whole loop being in python, I need to manually collect garbage between each run????

5) is there something special about track 244?  Is it much longer than the others?
No, just the average and for the other runs the second track was the point where performance fell off and that was different every time.

Brian McFee

unread,
Mar 3, 2015, 11:26:29 AM3/3/15
to lib...@googlegroups.com
inline:


On Tuesday, March 3, 2015 at 2:03:23 AM UTC-5, Stephen Etheridge wrote:
Hi Brian,
Answers in line, but I think no. 4 points to the issue:

A few questions about your setup:

1) what are your dependency versions?  (numpy, scipy, etc)

numpy==1.8.2
scikit-learn==0.14.1
scipy==0.15.1

2) do you have scikits.samplerate installed?
No, it would not load so I get a message about falling back to scipy.signal


Ok.  It shouldn't be that big of a deal, but libsamplerate is much faster than scipy, so it might be worth checking out. 
 
3) what are your beat tracking parameters?
Not sure what this means, I have "stolen" the example from the tutorial, i.e.

hop_length=64
...
y,sr=librosa.load(filename)
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr, hop_length=hop_length)



You might want to switch up to hop_length=512.  It will be the default going forward (librosa 0.4/current develop branch), and will save you lots of memory.
The precision of beats/onsets may suffer a little, but so far in my experience, it hasn't been too different.
 
4) are you running the entire loop in python, or spinning a new python instance for each track?
I was running the entire loop in python and I think this is where the issue is.  I have now written a python script which accepts the name of a track and only does BPM detection on that track and then shuts down.  I have written a wrapper around that to feed filenames in and that seems to work ok now without spawning the myriad [kworker] processes I was seeing and performance is fine.  To use a java expression, I wonder if, for the whole loop being in python, I need to manually collect garbage between each run????


Usually when I do this sort of thing, I use joblib.Parallel to spawn a bunch of python processes which do the heavy lifting, in a manner pretty similar to what you describe.  This should isolate any leaks to individual processes.

It's entirely possible that gc is to blame here, and you might try forcing a sweep every so often via the gc module.  I haven't run into this problem and can't say for sure whether this will work, but it's an idea.  If you're using parallelism via multiprocessing (not threading), then this shouldn't make any real difference.
 
5) is there something special about track 244?  Is it much longer than the others?
No, just the average and for the other runs the second track was the point where performance fell off and that was different every time.


Okay.

I hope some of this is helpful! 

Stephen Etheridge

unread,
Mar 4, 2015, 6:50:27 AM3/4/15
to lib...@googlegroups.com
Brian

I made the change to a hop length of 512 and incorporated destroying the onbjects between each run.  It now seems to be running pretty well (fingers crossed as I am most of the way through the first run).
Thanks for your help,
Stephen
Reply all
Reply to author
Forward
0 new messages