Passing arrays without overhead (preferably "by reference") to avoid duplication of complex code blocks in Matlab?

I have complex code blocks in a Matlab script that act on large, non-sparse arrays. The code performs many write operations on random elements in arrays, as well as read operations. Identical code must be executed for different (large) arrays (i.e., the same code blocks, except for different names of array variables).

I do not want to have long duplicated code blocks that differ only in array names.

Unfortunately, when I create a function to perform operations so that a block of code appears only once, performance slows down 10 or more times (presumably due to copying the array). However, I do not need the array copied. I would prefer to pass by reference, so the purpose of calling the function is ONLY to avoid duplication of code blocks. However, there seems to be no way to avoid copy-to-write semantics.

In addition, it is impossible (as I understand it) to create a script (and not a function) to achieve this, because the script must contain identical variable names as the calling script, so I would need a different script for each array on which I want to run the script. which gets nothing (I will still have duplicate blocks of code).

I considered creating an alias variable name to "replace" the array variable name of interest, in which case I could invoke a script and avoid code duplication. However, I cannot find a way to create an alias in Matlab.

Finally, I tried to write a function using the evalin() function and pass that variable the name of the array variable, but although this works, the performance is also much slower - about the same as passing arrays by value to a function (at least 10- multiple decline in performance).

I come to the conclusion that in Matlab it is impossible to avoid duplication of code blocks when performing complex operations on non-resonant arrays, trying to avoid the terrible costs that Matlab apparently offers, using any possible technique to avoid duplication of code blocks.

It’s so hard for me to believe, but I can’t find a way around this.

Does anyone know how to avoid duplicate blocks of code when performing the same intricate operations on multiple unresolved arrays in Matlab?

+8
matlab
source share
5 answers

As Loren noted in his blog , MATLAB supports in-line operations in matrices, which essentially encompass passing arrays by reference, modifying them in functions and returning the result. You seem to know this, but you are mistakenly claiming that since the script must contain identical variable names as the calling script. Here is a sample code that shows that this is wrong. When testing, copy it verbatim and save it as a function:

 function inplace_test y = zeros(1,1e8); x = zeros(1,1e8); tic; x = compute(x); toc tic; y = compute(y); toc tic; x = computeIP(x); toc tic; y = computeIP(y); toc tic; x = x+1; toc end function x=computeIP(x) x = x+1; end function y=compute(x) y = x+1; end 

Time results on my computer:

 Elapsed time is 0.243335 seconds. Elapsed time is 0.251495 seconds. Elapsed time is 0.090949 seconds. Elapsed time is 0.088894 seconds. Elapsed time is 0.090638 seconds. 

As you can see, the last two calls that use the function in place are equally fast for both input arrays x and y . In addition, they work as fast as running x = x+1 without a function. The only important thing is that the input and output parameters inside the function coincide. And there is one more thing ...

If I have to guess what is wrong with your code, I would say that you created the nested functions that you expect in place. And this is not so. So the code below will not work:

 function inplace_test y = zeros(1,1e8); x = zeros(1,1e8); tic; x = compute(x); toc tic; y = compute(y); toc tic; x = computeIP(x); toc tic; y = computeIP(y); toc tic; x = x+1; toc function x=computeIP(x) x = x+1; end function y=compute(x) y = x+1; end end Elapsed time is 0.247798 seconds. Elapsed time is 0.257521 seconds. Elapsed time is 0.229774 seconds. Elapsed time is 0.237215 seconds. Elapsed time is 0.090446 seconds. 

Bottom line - be careful with these nested functions.

+9
source share

You can try to put all your arrays in one array of cells and use an index on it, rather than referring to names. The function will still copy the arrays, but the script can do the job.

+4
source share

Another answer:

There is a good article on-site operations . Apparently, there may be two pitfalls:

  • (this is trivial, and you probably did it). You must use the same variable name in and out not only in the definition of the function, but also where you call it.
  • This only works if you call your function from ANOTHER FUNCTION, and not from the command line. Strange ... I tried, and although there is overhead, it is very small (for arrays 10,000 by 10,000 it was 1 second from the command line and 0,000361 seconds from another function).

If this does not work for you, you can use an undocumented function that allows you to perform the operation in place in the C ++ MEX file. This is unpleasant, but here is an article about it: Matlab mex in-place editing

+2
source share

The pen solution proposed by Brian L. does work, although the first call that modifies the wrapped data takes a lot of time (because it needs to make a copy of the original data).

Try the following:

SomeData.m

 classdef SomeData < handle properties X end methods function obj = SomeData(x) if nargin > 0 obj.X = x; else obj.X = []; end end end end 

LargeOp.m

 function directArray = LargeOp( someData, directArray ) if nargin > 1 directArray(1,1) = rand(1); else someData.X(1,1) = rand(1); directArray = []; end end 

Script for performance testing

 large = zeros(10000,10000); data = SomeData(large); tic LargeOp(data); toc tic large = LargeOp(data,large); toc tic LargeOp(data); toc tic large = LargeOp(data,large); toc 

results

 Elapsed time is 0.364589 seconds. Elapsed time is 0.450668 seconds. Elapsed time is 0.001073 seconds. Elapsed time is 0.443150 seconds. 
+2
source share

Depending on your needs, you can do this by executing a nested function .

 function A = evensarenegative(n) A = zeros(n,1); for i = 1:n if mod(i,2) nested1(i) else nested2(i) end end function nested1(i) A(i) = i; end function nested2(i) A(i) = -i; end end 

Here the functions use the same workspace, in particular the matrix A , so no variables are copied. I find this a convenient way to organize code, especially when I have many small (but possibly verbose) operations as part of a larger workflow.

+1
source share

All Articles