MATLAB is a pass by value language. I have a recursive function that processes pixel's neighbors. It is very expensive to make the copy of the image (in my case two images) each time the function is called.
I used global variables to solve the problem. Is there any other way to make a recursive function modify an array?
You have three options here, but maybe you don't need any of them, since Matlab used 'copy-on-write', i.e. variables are only copied if you modify them.
As #gnovice mentions, you can use a nested function. Variables used inside the nested function are shared between the nested function and the enclosing function. Nested functions are somewhat tricky to debug, and a bit more complicated to write/understand.
You can store your images as properties of a handle object, which is passed by reference.
You can write code differently in order to not use a recursive function, since Matlab isn't the best language for using those. If you have access to the image processing toolbox, you may be able to use functions like blockproc, or im2col to rewrite the function.
Finally, if you want to stay with your current scheme, I strongly suggest using persistent variables instead of globals.
MATLAB is not always pass-by-value, newer versions of MATLAB do pass-by-reference under some circumstances, see in-place operations and a more general discussion about MATLAB memory management in this SO post.
Without tail-call optimization it is inefficient to use recursion and MATLAB does not have it as far I know, but every recursion can be transformed into a loop.
If you make your recursive function a nested function within another function where the image data is stored, then the recursive function can modify the image data without needing to have it passed to it.
This is a common misconception. Although the sytanx of MATLAB is pass by value, it does not actually pass by value as in C. The interpreter is smart enough to only make copies when necessary. So you should just go ahead and pass by value and see if you run into memory problems.
As other posters have noted, you should try to avoid recursion in MATLAB anyway.
Related
This question already has answers here:
Are Matlab Matrices transferred pass-by-value or pass-by-reference?
(2 answers)
Closed 6 years ago.
I have several large matrices that should be passed to different functions many times in an iterative algorithm. How can I avoid the unnecessary copy of variables to the function to speed up the program? Is there any way to group these matrices in a structure or class and pass them by reference or pointer?
a=zeros(1000,1000);
b=zeros(1000,1000);
d=myfunction(a,b);
a=myfunction2(b,d);
....
Thanks.
Update: I should have provided more details as I see in the comments. I have several large matrices. Few of them remain constant in the program and others change in each function at each iteration. So if I pass these matrices by value, Matlab makes a copy of that, changes the value and again copy them as the output of the function and then they go out of scope and get destroyed and at each iteration all these unnecessary copying make the program awfully slow. If I were to program it in C++, I would use object oriented programming for these matrices and I would pass them as reference to the function but I don't know if that's possible in MATLAB.
Ander's comment is absolutely true. That said, if you do need the functions to modify the variable contents, then you might want to think about refactoring the code to try to avoid this scenario. I know the code that you posted is just a simplified example, but you could look at that and ask questions like "do a and b need to be initialized outside of the function? Could the function initialize them and return them instead?".
If you really can't get around it, then you could encapsulate the data in a handle class and pass the handle class to the functions instead.
I'm using a Matlab level 1 S-function several times in a model but don't want the mutual overwriting of global/persistent variables.
A solution could be work vectors but there is little documentation about level 1 S-function work vectors. Where do i get the SimStruct S for the ssSetNumRWork function?
Thanks!
The right thing to do is upgrade the code to be a level-2 S-Function, which shouldn't be difficult.
Level 1 m-code S-functions don't have work vectors (and all of the ssGet/Set functions are for c-code S-Functions anyway). A reason they aren't recommended any more is that they have limited functionality -- there's no nice way of getting around that without using Level 2 functionality.
You can use persistent variables (within each subfunction of a level-1 S-Function). But the point of global variables to enable them to be seen everywhere, so trying to use them without wanting everyone to see them seems pointless. (Note: you should never use global variables anyway.)
Having said that, if you really want to use Level-1 functionality, then within each S-Function you can use the getappdata and setappdata functions to act like work vector storage. But if you're going to go to that trouble, upgrading to a level-2 S-function will be easier anyway.
in a matlab script I have a vector which contains different instances of the same class. Now I would like to call the same function of each instance at the same time.
Is it, with tricky indexing, possible to do this WITHOUT a loop? For Example:
runner(1:100) = Human();
runner(:).run('fast'); % causes no error and no function call
In my project there is a vector with different neuronal networks (as objects). I tried to propagate all forward with one call.
Thanks for your time!
Well, there's one way if you're willing to modify your methods. What happens when you call something like runner(:).run('fast');? Rather than pass an instance of Human() to the run method 100 times it instead passes the entire vector of objects (an object array) to the method one time. Print out the object input from inside the method and see for yourself. Because nothing happens in your case, your run method must be written in such a way to ignore non-scalar objects. What you need to do is vectorize your methods. Depending on the nature of your methods, this may mean using for loops in some cases, but it will likely be the faster and more elegant option as it minimize the number of function calls.
Of course another option is to just call the run method 100 times using a for loop. If you really want "one call" then just hide the loop in a function or if you don't mind things to be a bit slower, use arrayfun which is nothing more than a function that hides a for loop:
arrayfun(#(obj)run(obj,'fast'),runner(:));
I have a two-dimensional and 1-D arrays of different variables of a system which characterize an Equilibrium state of the system from where the next configurations going to evolve from. Now i need to save the data in these arrays at the specific situation and proceed, so how should i write on the declaration (the syntax) of the main program and also in the subroutine which use these arrays to be delivered to them by adjustable-size array method of passing arrays?
Uuugh, sorry, but I'm not quite clear on what you are asking.
Are you interested in the SAVE statement, which enables a variable to retain its previous state, once for example, a subroutine is called again?
I have variables which are of double type I want them to be float. Is there a way to force a variable to be float and not double, also, Is there a way to do it in some global way for all functions and sub functions with few lines at the start of the main function? I have many functions and they use many temporary variables and create variables that they return. Going over all of my functions and changing them will be very difficult.
My rational for this request:
I'm writing the MATLAB program in order to simulate an algorithm which I'll then implement in hardware, I want to make sure that using 32bit as the size of my signals will not cause calculation errors.
Using B=single(A) as suggested by #cbz, or defining arrays as SINGLE, such as by calling B=zeros(3,3,'single') creates "floats" in Matlab.
There is no way to globally turn Matlab into a "float" environment. Although most lower-level functions are implemented for single as well (with a few exceptions, for example those mentioned in the help to DOUBLE), many high-level builtin functions will only work with double.
In other words, you'll have to manually define your variables as single, you'll have to periodically check that the variables haven't been quietly converted to double, and in the end, your code might not work if it needs a function that isn't implemented for single yet.
The MATLAB equivalent to 'float' is 'single. You can convert using
B = single(A).
That said, your assumption that this amounts to 32-bit might need revisiting. It's not as simple as that.