using property 2x slower: myprop = [myprop(2:end); new]

4 views (last 30 days)
How to speedup circular buffer ...
There are different ways to implement a circular buffer. The most common approach in matlab is a copy-all:
circBuff = [circBuff(2:end), newest]
As this results in copying the whole buffer each time you add something, I worked recently on an optimized way of circular buffer for large buffer size implementing the class circVBuf: MatlabCentral-FileExchange: circVBuf
For a better circular buffer I implemented different ways to append values. For small buffers using the simple method of copy-all is the fastest, but for large buffer size it is much better to switch to a double buffered approach.
Depending on the buffer size I want to allow different append functions to be used, but it seems as if I cannot reach to the speed of the copy-all method inside an object if the buffer is a property of the class:
a) obj.raw = [ obj.raw(2:end,:); vec(:) ]
b) raw = [ raw(2:end,:); vec(:) ]
‘a’ takes twice as much time in matlab 2014a as ‘b’:
It seems to me as if matlab makes an internal copy when using ‘a’, which it does not when using ‘b’. But in OO programming I cannot avoid ‘a’ and switch to ‘b’.
Any idea how to speedup ‘a’?
  1 Comment
Matt J
Matt J on 29 Jun 2014
You should mention what version of MATLAB you are using and whether obj is a handle or value object. Indexing was found to be slower in handle classes in some older versions of MATLAB.

Sign in to comment.

Answers (1)

Geoff Hayes
Geoff Hayes on 26 Jun 2014
Your circular buffer class is pretty neat. I downloaded the package and ran the plot_circVBuf_speedtest function and observed results that did indicate that the circVBuf class is slower when it comes to copying data as obj.raw = [ obj.raw(2:end,:); vec(:) ]. Note that the plot results from this function did not look like the image above which could be explained by running the software in my environment:
I did wonder about the legend for the plot though - the results from the wtimes matrix are used to plot the circVBuf output in red and the other in blue, but the legend shows the opposite.
One thing I did notice was the following lines of code at the beginning of the circVBuf_speedtest function
cvbuf1 = circVBuf(int64(bufferSz),int64(vectorLen),appendType);
cvbuf2 = nan(bufferSz,vectorLen,'double');
cvbuf1 is clearly the instance of the circVBuf class whose constructor takes the buffer size and vector length as inputs and passes both to the setup function where the raw data member is initialized as
obj.raw = nan(bufSize*2, vecSize, 'double');
Note how twice as much memory is allocated to this raw array as opposed to cvbuf2. I changed the initialization of the latter array to
cvbuf2 = nan(bufferSz*2,vectorLen,'double');
The results were interesting with less (but still noticeable) differences between the two methods:
I then switched the order in which the calculations were made - i.e. the tic/toc calculations for cvbuf2 before that of cvbuf1. These were more interesting, showing that the circular buffer class performed better than the other:
All this to say that it doesn't appear that the copying of the raw data as a data member with a class instance is necessarily slower than that for the direct array copy. Just that more tests (hundreds?) may be needed when trying to compare the results of these two methods of copying data into a circular buffer.
  5 Comments
Jens Henrik Göbbert
Jens Henrik Göbbert on 29 Jun 2014
Geoff: "Note how twice as much memory is allocated to this raw array as opposed to cvbuf2."
circVBuf must allocate twice as much memory for appendType==0, but the max usable buffer size is only half of it. If you compare two implementations for a circular buffer, only the usable buffer size should be considered, as the more memory allocated in circVBuf is forced by the algorithm used for append.
But if we test appendType==1, you are right: this double buffering is not required and just slows down the code. This is a great hint this speedsup appendType==1 almost twice!
Now appendType==1 looks as I would expect it. It is still a bit slower, as some more informations are available through circVBuf and have to be computed.
Now I will think of a fast possibility to switch between appendType==0 and appendType==1 on the fly.
Jens Henrik Göbbert
Jens Henrik Göbbert on 29 Jun 2014
Edited: Jens Henrik Göbbert on 29 Jun 2014
The optimum would be to habe circVBuf automatically switch between appendType==0 and appendType==1 depending on the buffer size and the size of the data to be appended.
I did the first steps towards this possibility with version 0.9.5 today. You can set the appendType while creating a circVBuf object. Whatever appendType is set, the function name for append() is always the same now as this is a function pointer as a property of the object.
Next would be to add an automatic test to choose the best appendType.
I will have to see, how much code generation will speedup things, but currently matlab does not support compiled classes, but only compiled functions ...
Anyway, thanks for your help Geoff.

Sign in to comment.

Categories

Find more on Specifying Target for Graphics Output in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!