3

I often optimize some matlab routines by implementing them in mex. This works fine so far - but whenever creating the return mxArray, it gets preinitialized as I build it with mxCreateNumericArray.
In most of my work, I do not need the memory to be preallocated (zeroed). So sad - I can not find a matching command for that purpose (allocating memory without zeroing).

So my question could be answered in two ways:

  1. Which command do I have to call for creating a mxArray without zeroing the contents?
  2. How can I build a mxArray without allocating memory for Pr (and Pi)-field, which I would later allocate by mxMalloc.

One idea is building the Array with size (0,0) - but is this the ultimate solution?

Bastian Ebeling
  • 1,138
  • 11
  • 38
  • 1
    Not sure if it helps, but perhaps you can get some inspiration from the question [Faster way to initialize arrays](http://stackoverflow.com/questions/14169222/faster-way-to-initialize-arrays-via-empty-matrix-multiplication-matlab) – Dennis Jaheruddin Dec 10 '13 at 15:38

3 Answers3

2

I guess, building a size (0,0) matrix is as close as it gets to a kind of "empty" constructor. Afterwards you'll have to resize the array using mxMalloc or mxRealloc.

I doubt this will result in a noticable performance gain though, unless you're handling really large arrays.

sebastian
  • 9,526
  • 26
  • 54
  • Hi, this sounds somehow clear. I tried with creating a 12345 x 12345 array build up with mxCreateNumericArray resulting in 5.7992 seconds by timeit against creating with 0,0 and using mxMalloc and mxSetDimensions for the same data and size resulting in 5.8946 seconds. This is strange, isn't it? (There is some uncompression done also within the time, exactly the same for both calls.) – Bastian Ebeling Dec 10 '13 at 08:20
  • That's kind of weird, yep. Are the timings comparable for multiple test-runs? If so, it seems matlab does a pretty good job... – sebastian Dec 10 '13 at 11:19
  • I used the last few hours for testing different methods. Combined with your lines here, I think, I can answer my question on my own - and thus I'll post my results as an answer soon here. Thanks – Bastian Ebeling Dec 10 '13 at 12:28
  • The suggestion made here sounds sensible, but in my experience doesn't provide any benefit. I'm not sure why, but my guess is that mxMalloc also drags all allocated memory through the cache. – user664303 Dec 10 '13 at 15:06
2

With those lines from sebastian I played around. I think, the following lines show the answer to my question.
In words - even with zeroing the space the result is fast.
With my current application I tested four different scenarios:

  1. plhs[0] = mxCreateNumericArray(targetDimCount, targetDims, targetClass, mxREAL);
  2. plhs[0] = mxCreateNumericArray(0, 0, targetClass, mxREAL); mxSetData(plhs[0],mxMalloc(destLen_in_Bytes));
  3. plhs[0] = mxCreateNumericArray(0, 0, targetClass, mxREAL); mxSetData(plhs[0],mxRealloc(mxGetData(plhs[0]),destLen_in_Bytes));
  4. plhs[0] = mxCreateUninitNumericArray(targetDimCount, targetDims, targetClass, mxREAL);

resulting in those timings (for allocated matrices of size given in column one)

 size       time 1       time 2       time 3       time 4

 1000     0.037401     0.037263     0.039294     0.037628
 2000     0.14906      0.14937      0.15278      0.14917
 3000     0.33497      0.33449      0.34601      0.33749
 4000     0.61207      0.60546      0.61563      0.60086
 5000     0.94057      0.93076      0.96147      0.95723
 6000     1.3497       1.3475       1.3794       1.3559
 7000     1.837        1.8265       1.8776       1.846
 8000     2.398        2.3893       2.4625       2.3885
 9000     3.0264       3.047        3.1374       3.0339
10000     3.7658       3.7677       3.8392       3.7862
20000    15.208       14.968       15.404       15.143
30000    13.583       13.58        13.955       13.648
50000    13.291       13.236       13.535       13.478

With a view on these numbers, my opinion is, that reallocating is a bad idea (but not so bad, as the timing shows) and zeroing the values is not a very big efford. Okay - one can further wonder on the behaviour between 10000 to 30000 - but that would be more scientific. Using malloc (only for testing purposes) is not working, as the allocated storage needs to be for a plhs - and it crashes unless the storage is allocated by mx***

Bastian Ebeling
  • 1,138
  • 11
  • 38
  • 1
    I have tried to tackle the same problem myself, and have not found a clean solution. It would be worth seeing timings for using malloc() instead of mxMalloc() (not that you should do this in practice), as the timings suggest that mxMalloc is dragging all allocated memory through the cache (since the code gets slower as the allocated size increases). – user664303 Dec 10 '13 at 15:04
  • Also try using mxSetPr instead of mxSetData to see if that makes any difference. – user664303 Dec 10 '13 at 15:13
  • 1
    @user664303 - I can not find a difference in using mxSetPr - and from the doc it only uses a typed pointer not a void pointer. – Bastian Ebeling Dec 11 '13 at 09:25
  • Take a look at James Tursa's ***uninit*** utility on the File Exchange: http://www.mathworks.com/matlabcentral/fileexchange/31362-uninit-create-an-uninitialized-variable-like-zeros-but-faster – Yair Altman Mar 11 '14 at 08:23
1

Another possible option might be to us the undocumented function mxFastZeros. It's one of many undocumented mex functions. You can read about it's use in this Matlab Central answer. I'd be interested to know if it does anything different that just creating a zero size matrix.

horchler
  • 18,384
  • 4
  • 37
  • 73