What extra data is stored by an anonymous function?
14 views (last 30 days)
Show older comments
Matt J
on 10 Feb 2014
Commented: Philip Borghesani
on 6 Mar 2014
I have learned recently, that anonymous functions can carry around large amounts of extra data from the workspace that they don't use, even if this data is created after the anonymous function. The following example, together with the FUNCTIONS comand, illustrates this,
function fun=test
a=1;
b=2;
c=3;
fun=@(x)x+b+a;
a=7;
b=rand(1000);
c=5;
q=3;
r=4;
end
Now, back in the base workspace, when I apply the functions() command to 'fun', I see
>> fun=test; s=functions(fun); s.workspace{:}
ans =
b: 2
a: 1
ans =
fun: @(x)x+b+a
a: 1
b: [1000x1000 double]
c: 3
I would like to understand (with official documentation if possible) what rules anonymous functions use to decide what data to carry around. The above seems to suggest that s.workspace{1} will always contain the external variables and their values that the anonymous function actually uses. Meanwhile s.workspace{2} seems to contain updates to variables that came into scope before fun was defined. Am I correct that these are the rules? But if so, then why, in the above, does s.workspace{2} contain an update to b, but not to a and c?
0 Comments
Accepted Answer
Philip Borghesani
on 10 Feb 2014
Edited: Philip Borghesani
on 10 Feb 2014
I will start my answer with a quote from the documentation of functions:
The functions function is used for internal purposes, and is provided
for querying and debugging purposes. Its behavior may change in
subsequent releases, so it should not be relied upon for programming
purposes.
The output from this function for this code WILL change in a future version of MATLAB and can change in your current version:
>> fun=test; s=functions(fun); s.workspace{:}
ans =
b: 2
a: 1
ans =
fun: @(x)x+b+a
a: 1
b: [1000x1000 double]
c: 3
>> feature accel off
>> fun=test; s=functions(fun); s.workspace{:}
ans =
b: 2
a: 1
ans =
fun: @(x)x+b+a
a: 7
b: [1000x1000 double]
c: 5
q: 3
r: 4
workspace{2} will contain the final state of the function workspace at exit but might not take into consideration non-visible changes to that workspace that are optimized by the jit.
The contents of workspace{2} should be considered completely version dependent and subject to removal or being inconsistent due to current and future optimizations.
3 Comments
Philip Borghesani
on 11 Feb 2014
Anything returned by functions or even the existence of the function functions is subject to change but the contents or existence of workspace{2} is known to change. There is a slight difference there.
One note on the contents you are seeing of workspace{2}. This is not a copy of variables in the function but a pointer to the actual workspace. Nested functions or multiple anonymous functions will see the same values in workspace{2} even if they are changed by a nested function so the memory used is not usually noticed and there is little performance overhead caused by this data as long as parfor is not in the equation.
More Answers (2)
Matt J
on 4 Mar 2014
Edited: Matt J
on 4 Mar 2014
3 Comments
Philip Borghesani
on 6 Mar 2014
I can't guarantee it but I believe you are correct, workspace{2} is only needed with nested functions.
James Tursa
on 6 Mar 2014
Edited: James Tursa
on 6 Mar 2014
This topic has already been addressed in this thread:
For convenience I will repeat my answer here:
When you create an anonymous function handle, all variables that are not part of the argument list are regarded as constants. Shared data copies of them are made at the time you create the function handle and actually stored inside the function handle itself. They retain their value and use up memory even if you change the source of the "constant" later on in your code. E.g., if you had done this:
A = v;
f = @(x) A*x; % could have done f = @(x) v*x; and got same result
A = 2*v;
the last line has no effect on the function handle f output (EDIT). Note that if A happens to be a very large variable, its memory effectively gets "locked up" inside f and can only be cleared by clearing (or re-defining) f. E.g., in the above code snippet, the 2nd line will put a shared data copy of A inside of f. The 3rd line will cause this shared data copy to essentially become a deep data copy (it gets unshared with A at that point).
Bottom line is, once the anonymous function gets created the standard rules for shared data copies applies. At least that was the behavior I observed last year. I may need to re-examine this ...
6 Comments
See Also
Categories
Find more on Get Started with MATLAB in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!