Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Strange Anonymous Behavior

Subject: Strange Anonymous Behavior

From: Ben

Date: 6 Nov, 2012 21:25:08

Message: 1 of 5

This might get a little complicated, but hopefully I can explain my predicament.

I have a matlab function (let's call it "sift.m") that stores, among other things, a function (an anonymous function) in an array of structs, i.e.
s(1).func = @(x) [x,0,0];

I save that struct into a .mat file and load in into the base workspace. Then, I send the "loaded" variable to another function ("solveme.m") that uses the ode45, which in turn uses a function called "StateEstimate" defined separately in the solveme.m file. StateEstimate accesses the anonymous function to calculate a needed value. The strange behavior: I run this with the profiler, it takes about 45 seconds and tells me the StateEstimate takes most of the time. I go back to my sift.m file and change it to an inline function, i.e.
s(1).func = inline('[x,0,0]','x');

When I run this, it takes 20 seconds, spending 5 seconds in the inline eval and 15 in the StateEstimate. I go back to the anonymous and run the function -- it takes over 2 minutes before I kill the process (ctrl-c). The profiler tells me that 9 seconds were spent in StateEstimate and 125 seconds were spent in the anonymous function! And not only that, it says the function is coming from sift.m, which surprises me since I saved the anonymous function off and loaded it back in.

First: Why is the behavior of the anonymous function not consistent? Why does it hang?
Second: Why/where is the "sift.m" information associate with the saved data?
Third: Why is inline faster than anonymous???

I appreciate any insight into these quesitons. I have my code working fine with inline, but wanted the speed increase that anonymous promises. If I have to stay with inline, that wouldn't be the end of the world, but I'd prefer not to. Ideas?

Subject: Strange Anonymous Behavior

From: Ben

Date: 7 Nov, 2012 16:18:08

Message: 2 of 5

"Ben" wrote in message <k7bv7k$709$1@newscl01ah.mathworks.com>...
> This might get a little complicated, but hopefully I can explain my predicament.
>
> I have a matlab function (let's call it "sift.m") that stores, among other things, a function (an anonymous function) in an array of structs, i.e.
> s(1).func = @(x) [x,0,0];
>
> I save that struct into a .mat file and load in into the base workspace. Then, I send the "loaded" variable to another function ("solveme.m") that uses the ode45, which in turn uses a function called "StateEstimate" defined separately in the solveme.m file. StateEstimate accesses the anonymous function to calculate a needed value. The strange behavior: I run this with the profiler, it takes about 45 seconds and tells me the StateEstimate takes most of the time. I go back to my sift.m file and change it to an inline function, i.e.
> s(1).func = inline('[x,0,0]','x');
>
> When I run this, it takes 20 seconds, spending 5 seconds in the inline eval and 15 in the StateEstimate. I go back to the anonymous and run the function -- it takes over 2 minutes before I kill the process (ctrl-c). The profiler tells me that 9 seconds were spent in StateEstimate and 125 seconds were spent in the anonymous function! And not only that, it says the function is coming from sift.m, which surprises me since I saved the anonymous function off and loaded it back in.
>
> First: Why is the behavior of the anonymous function not consistent? Why does it hang?
> Second: Why/where is the "sift.m" information associate with the saved data?
> Third: Why is inline faster than anonymous???
>
> I appreciate any insight into these quesitons. I have my code working fine with inline, but wanted the speed increase that anonymous promises. If I have to stay with inline, that wouldn't be the end of the world, but I'd prefer not to. Ideas?

Alright, I think I've figured it out. I'll post this in case someone google-stumbles (googumbles? stoogles?) onto this entry. Comment number 6 from a Loren's blog entry (http://blogs.mathworks.com/loren/2012/08/29/thoughts-about-anonymous-functions/ -- thanks, Iain) led me to this page that helped: http://homepages.inf.ed.ac.uk/imurray2/compnotes/octave_matlab.html#capture

Basically, it seems like MATLAB saves the environment, not just the pertinent variables. So when I assign the anonymous function in sift.m, MATLAB remembers the other variables sift.m assigns to my structure, ie
function s = sift
   s(1).a = rand(100,1);
   s(1).b = rand(100,1);
   s(1).func = @(x) [x 0 0];
%... a lot more things happen
end

If I put the anonymous function in a separate function in sift.m, it performs better:
function s = sift
   s(1).a = rand(100,1);
   s(1).b = rand(100,1);
   s(1).func = GetAnonFunc;
%... a lot more things happen
end
function out = GetAnonFun
     out = @(x) [x 0 0];
end

With this approach, profiler consistently shows anonymous function being faster than inline.

The memory allocation seems to be the reason for the slow down and the non-determinate behavior. MATLAB has to load in a lot of peripheral information (which, frustratingly, didn't show up in the workspace when I stopped in the debugger and the workspace window wouldn't let me switch the stack around...)

So, to answer my questions directly:
> First: Why is the behavior of the anonymous function not consistent? Why does it hang?
The extra stuff loaded in memory bogs things down.
> Second: Why/where is the "sift.m" information associate with the saved data?
"Why" is because that's how MATLAB does things...
"Where" is not known.
> Third: Why is inline faster than anonymous???
It's not -- all is right with the world. The extra memory requirements caused MATLAB to take longer.

I wish MATLAB didn't do that, but at least I have a work around.

Subject: Strange Anonymous Behavior

From: Ben

Date: 7 Nov, 2012 16:31:08

Message: 3 of 5

> The memory allocation seems to be the reason for the slow down and the non-determinate behavior.

Sorry, "non-determinate" implies the results of the calculation wasn't the same. I did not mean to imply that. I should have said the vastly varying computation time. It was not the results of the calculation I was questioning, but the time the calculations took.

Subject: Strange Anonymous Behavior

From: Steven_Lord

Date: 7 Nov, 2012 17:20:21

Message: 4 of 5



"Ben " <ben-walker@northwestern.edu> wrote in message
news:k7e1k0$la4$1@newscl01ah.mathworks.com...
> "Ben" wrote in message <k7bv7k$709$1@newscl01ah.mathworks.com>...

*snip*

>> I appreciate any insight into these quesitons. I have my code working
>> fine with inline, but wanted the speed increase that anonymous promises.
>> If I have to stay with inline, that wouldn't be the end of the world, but
>> I'd prefer not to. Ideas?
>
> Alright, I think I've figured it out. I'll post this in case someone
> google-stumbles (googumbles? stoogles?) onto this entry. Comment number
> 6 from a Loren's blog entry
> (http://blogs.mathworks.com/loren/2012/08/29/thoughts-about-anonymous-functions/
> -- thanks, Iain) led me to this page that helped:
> http://homepages.inf.ed.ac.uk/imurray2/compnotes/octave_matlab.html#capture
>
> Basically, it seems like MATLAB saves the environment, not just the
> pertinent variables.

That is correct. See the "Variables in the Expression" section on this
documentation page:

http://www.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html

> So when I assign the anonymous function in sift.m, MATLAB remembers the
> other variables sift.m assigns to my structure, ie
> function s = sift
> s(1).a = rand(100,1);
> s(1).b = rand(100,1);
> s(1).func = @(x) [x 0 0];
> %... a lot more things happen
> end

If you look at the workspace of that anonymous function using the diagnostic
function named FUNCTIONS:

s = sift;
info = functions(s.func)

you should see a field in the output named 'workspace' that contains
information about the variables the anonymous function "remembers." This
information is read-only; there's no way to cause the anonymous function to
"forget" a piece of what you see in this output. Note: you should _not_ use
FUNCTIONS as a part of your function's regular execution but only for
debugging and diagnostics, as indicated in its help text.

> If I put the anonymous function in a separate function in sift.m, it
> performs better:
> function s = sift
> s(1).a = rand(100,1);
> s(1).b = rand(100,1);
> s(1).func = GetAnonFunc;
> %... a lot more things happen
> end
> function out = GetAnonFun
> out = @(x) [x 0 0];
> end

In that situation, there's less in the workspace that it may need to
"remember."

> With this approach, profiler consistently shows anonymous function being
> faster than inline.
>
> The memory allocation seems to be the reason for the slow down and the
> non-determinate behavior. MATLAB has to load in a lot of peripheral
> information (which, frustratingly, didn't show up in the workspace when I
> stopped in the debugger and the workspace window wouldn't let me switch
> the stack around...)
>
> So, to answer my questions directly:
>> First: Why is the behavior of the anonymous function not consistent? Why
>> does it hang?
> The extra stuff loaded in memory bogs things down.
>> Second: Why/where is the "sift.m" information associate with the saved
>> data?
> "Why" is because that's how MATLAB does things...
> "Where" is not known.

Inside the anonymous function. You can read that information with FUNCTIONS;
you cannot change it (short of remaking the anonymous function.)

*snip*

BTW this is why you can do something like this, where f only accepts the
"data" input:

n = 2;
f = @(x) x.^n;
f(1:10)

as opposed to the inline approach where you need to specify both the data
input AND the "helper" input when you call g:

g = inline('x.^n', 'x', 'n');
n = 2;
g(1:10, n)

Compare:

n = 2;
h = inline('x.^n', 'x');
h(1:10) % error; undefined function or variable n

--
Steve Lord
slord@mathworks.com
To contact Technical Support use the Contact Us link on
http://www.mathworks.com

Subject: Strange Anonymous Behavior

From: Ben

Date: 7 Nov, 2012 22:56:15

Message: 5 of 5

> If you look at the workspace of that anonymous function using the diagnostic
> function named FUNCTIONS:
>
> s = sift;
> info = functions(s.func)
>
> you should see a field in the output named 'workspace' that contains
> information about the variables the anonymous function "remembers." This
> information is read-only; there's no way to cause the anonymous function to
> "forget" a piece of what you see in this output. Note: you should _not_ use
> FUNCTIONS as a part of your function's regular execution but only for
> debugging and diagnostics, as indicated in its help text.
>


I didn't know about FUNCTIONS. Thanks for the info.

 ...snip...


> BTW this is why you can do something like this, where f only accepts the
> "data" input:
>
> n = 2;
> f = @(x) x.^n;
> f(1:10)
>
> as opposed to the inline approach where you need to specify both the data
> input AND the "helper" input when you call g:
>
> g = inline('x.^n', 'x', 'n');
> n = 2;
> g(1:10, n)
>
> Compare:
>
> n = 2;
> h = inline('x.^n', 'x');
> h(1:10) % error; undefined function or variable n
>

Yes, I understand that the helper variable 'n' is saved. This is cool, helpful behavior. But it seemed that other things were being saved, too. In the below example, m is not saved in the "workspace" field returned by FUNCTIONS.

n = 4;
m = 5;
f = @(x) x.*n;
s = functions(f)
s =
     function: '@(x)x*n'
         type: 'anonymous'
         file: ''
    workspace: {[1x1 struct]}
s.workspace{1}
ans =
    n: 4

But if the function is all of a sudden a part of a structure, then the "workspace" of the anonymous function saves way too much information:

b.n = 4;
b.m = 5;
b.f = @(x) x.*(b.n);
b.f(3) % see, it works!
ans =
    12
s = functions(b.f)
s =
     function: '@(x)x.*(b.n)'
         type: 'anonymous'
         file: ''
    workspace: {[1x1 struct]}
t = s.workspace{1}
t =
    b: [1x1 struct]
t.b
ans =
    n: 4
    m: 5

In this instance, I only need b.n saved. Unfortunately, b.m is also saved, so for my application, this "extra" stuff that's saved (the non-necessary variable 'm') caused significant lag for my system.

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us