Cell Array of Function Handles Leaks Memory

2 views (last 30 days)
I have a memory leak problem when I generate a cell array of functions in a for loop. An example would be like this:
for ii = 1:100000
[L1,L1str] = getSet(ii,ii+1)
end
If I run this code in Matlab R2013a, the memory use will increase until I am out of memory. Even when I clear all variables in the workspace, the memory used by matlab is not decreasing. Is this a known problem? If not, how do I solve it?
function [L1,L1str]=getSet(kl1x,kl1y)
kl1xstr = num2str(kl1x,32);
kl1ystr = num2str(kl1y,32);
L1str{1,1} = strcat('(sin((',kl1xstr,').*x).*exp(-1i.*(',kl1ystr,').*y))');
L1str{1,2} = strcat('((',kl1xstr,').*cos((',kl1xstr,').*x).*exp(-1i.*(',kl1ystr,').*y))');
L1str{1,3} = strcat('(-1i.*(',kl1ystr,').*sin((',kl1xstr,').*x).*exp(-1i.*(',kl1ystr,').*y))');
L1str{1,4} = strcat('(-(',kl1xstr,').^2.*sin((',kl1xstr,').*x).*exp(-1i.*(',kl1ystr,').*y))');
L1str{1,5} = strcat('(-(',kl1ystr,').^2.*sin((',kl1xstr,').*x).*exp(-1i.*(',kl1ystr,').*y))');
L1str{1,6} = strcat('(-1i.*(',kl1xstr,').*(',kl1ystr,').*cos((',kl1xstr,').*x).*exp(-1i.*(',kl1ystr,').*y))');
L1{1,1} = str2func(strcat('@(x,y)',L1str{1,1} ));
L1{1,2} = str2func(strcat('@(x,y)',L1str{1,2} ));
L1{1,3} = str2func(strcat('@(x,y)',L1str{1,3} ));
L1{1,4} = str2func(strcat('@(x,y)',L1str{1,4} ));
L1{1,5} = str2func(strcat('@(x,y)',L1str{1,5} ));
L1{1,6} = str2func(strcat('@(x,y)',L1str{1,6} ));
end

Accepted Answer

James Tursa
James Tursa on 6 May 2014
Edited: James Tursa on 6 May 2014
I suspect this is a problem with the MATLAB function parser and acceleration techniques used behind the scenes. Unfortunately, I haven't been able to construct a workaround yet. Here is what I observed to come to my conclusions.
1) In the past, when examining the guts of MATLAB variables inside C-mex routines, I recall noticing variable types that I had not typically observed. They seemed to be associated with variables inside functions that get created and then "remembered" off to the side, so that if the same branch of code was run again the variable was fetched from this "store" instead of being created again. My guess is that this was/is an attempt at performance boosting.
2) When I replace your num2str code with static strings, the huge memory increase pretty much goes away. E.g.,
% kl1xstr = num2str(kl1x,32);
% kl1ystr = num2str(kl1y,32);
kl1xstr = '000000';
kl1ystr = '000000';
3) When I run your original code with a smaller loop size (so I don't run out of memory), and then re-run it, there is no memory increase on the re-run.
My guess, then (heavy emphasis on guess), is that the performance features in parsing your function are creating a gazillion strings stored off to the side so that if the code is run again those strings can be fetched instead of being created. So the memory isn't leaked in a strict sense (MATLAB knows it is using it), but it sure is as far as the user (you) is concerned.
To create a workaround, I have tried the following to no avail:
- Different function instead of num2str e.g., (sprintf)
- A mex function to create the string (e.g., num2strexact)
- A mex function to alter the strings in-place
- Creating the string manually one char at a time
- Making the string global and then modifying it inside the function
- Passing in the individual strings instead of creating them in the function
- Turning performance features off via "feature accel off"
- Tried the function pack
Nothing has worked so far ... the accel features are too smart, so I am unable to help you as of yet.
I would report this to TMW via their Bug Report section if it is not already there.
  1 Comment
Michael
Michael on 22 May 2014
Only for your information. When I use inline instead of str2fun this problem do not appear. I also recognized randomly appearing errors when i use anonymous functions and for some reason the calculated value is different between the anonymous function and the inline function. This also appears randomly.

Sign in to comment.

More Answers (1)

Philip Borghesani
Philip Borghesani on 22 May 2014
This function generates function handles that run faster in much less time and uses little memory overhead. I will also assert that it is much easier to read and maintain.
function [L1,L1str]=getSet(kl1x,kl1y)
function r=f1(x,y)
r=(sin(kl1x.*x).*exp(-1i.*kl1y.*y));
end
function r=f2(x,y)
r=(kl1x.*cos(kl1x.*x).*exp(-1i.*kl1y.*y));
end
function r=f3(x,y)
r=(-1i.*kl1y.*sin(kl1x.*x).*exp(-1i.*kl1y.*y));
end
function r=f4(x,y)
r=(-kl1x.^2.*sin(kl1x.*x).*exp(-1i.*kl1y.*y));
end
function r=f5(x,y)
r=(-kl1y.^2.*sin(kl1x.*x).*exp(-1i.*kl1y.*y));
end
function r=f6(x,y)
r=(-1i.*kl1x.*kl1y.*cos(kl1x.*x).*exp(-1i.*kl1y.*y));
end
L1{1,1} = @f1;
L1{1,2} = @f2;
L1{1,3} = @f3;
L1{1,4} = @f4;
L1{1,5} = @f5;
L1{1,6} = @f6;
end
James gave a good explanation of the cause of the problem. This is one more reason why avoiding eval and str2fun which is just a glorified eval is a good best practice.

Categories

Find more on Characters and Strings 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!