2
votes

Well, I am trying to implement an algorithm on Matlab. It requires the usage of a slice of an high dimensional array inside a for loop. When I try to use the logical indexing, Matlab creates an additional copy of that slice and since my array is huge, it takes a lot of time.

slice = x(startInd:endInd);

What I am trying to do is to use that slice without copying it. I just need the slice data to input a linear operator. I won't update that part during the iterations.

To do so, I tried to write a Mex file whose output is a double type array and whose size is equal to the intended slice data size.

plhs[0] = mxCreateUninitNumericMatrix(0, 0, mxDOUBLE_CLASS,mxREAL); % initialize but do not allocate any additional memory
ptr1 = mxGetPr(prhs[0]); % get the pointer of the input data

Then set the pointer of the output to the starting index of the input data.

mxSetPr(plhs[0], ptr1+startInd);
mxSetM(plhs[0], 1);
mxSetN(plhs[0], (endInd-startInd)); % Update the dimensions as intended

When I set the starting index to be zero, it just works fine. When I try to give other values than 0, Mex file compiles with no error but Matlab crashes when the Mex function is called.

slice = mex_slicer(x, startInd, endInd);

What might be the problem here?

2
Can you show how you actually need to access this array slice inside your for loop? Maybe you don't need to assign it to an intermediate variable? - nekomatic
I guess your crash in the mex file results from assigning the same memory area to two matlab variables. Matlab does not know that you did this and will crash when reallocating one of the variables. To avoid copying memory you should not create a copy of your slice in a separate variable but try to index the original big field. You can do so with index arrays like in your example. But I am not absolutely sure that matlab will not copy the data internally. - Georg W.
Even if I don't assign it to an intermediate variable, same problem still exists. The reason for that, I guess, is that; when doing logical indexing, it creates the index array of 'size = size([startInd:endInd])'. So, what I try to do here is a bit of hacking. Just give the pointer to a memory place where I know what exists and tell how many elements to obtain after that memory. I don't want to create any index array, too. (size of the index array in the order of 2 millions). - Fatih

2 Answers

0
votes

The way you assign the data pointer to the array, it means that MATLAB will attempt to free that memory when the array is deleted or has something else assigned to it. Attempting to call free using a pointer that was not obtained by malloc will cause a crash.

Unfortunately, MATLAB does not support "views", arrays that point at parts of a different array. So there is no way to do what you want to do.

An alternative solution would be to:

  • store your data differently, so that it doesn't take as much time to index (e.g. in smaller arrays)?

  • perform all your computations in C or C++ inside a MEX-file, where you can very simply point at sub-ranges of a larger data block.

0
votes

See this FEX submission on creating MATLAB variables that "point" to the interior data of an existing variable. You can either do it as a shared data copy which is designed to be safe (but incurs some additional overhead), or as an unprotected direct reference (faster but risks crashing MATLAB if you don't clear it properly).

https://www.mathworks.com/matlabcentral/fileexchange/65842-sharedchild-creates-a-shared-data-copy-of-a-contiguous-subsection-of-an-existing-variable