Question

Hello fellow Earth hitchhikers, I have just stumbled upon how slow are anonymous functions in Matlab. However, I can't find a convenient alternative. I need to generate about 12 of these channels, each of them having 8 small functions. Here is one for example.

channels = [];
channel.name   = 'CHNAF';
channel.area   = 10;
channel.g      = 0.013;
channel.E      = 87.39;
channel.alphaa = @(V,ion) 0.9*(V+19)/(1-exp(-(V+19)/10));
channel.betaa  = @(V,ion) 36*exp(-0.055*(V + 44));
channel.infa   = @(a,b,V) a/(a+b);
channel.taua   = @(a,b,V) 1/(a+b);
channel.na     = 3;
channel.alphai = @(V,ion) 0.315*exp(-0.3*(V + 44));
channel.betai  = @(V,ion) 4.5/(1 + exp(-(V + 11)/5));
channel.infi   = @(a,b,V) a/(a+b);
channel.taui   = @(a,b,V) 1/(a+b);
channel.ni     = 1;
channels = [channels channel];

The generation is not a problem. But I want to use these functions and the following code makes it very very slow.

ch    = channels(1);
curr  = curr + ch.area*ch.g*ch.m^ch.na*ch.h^ch.ni*(V-ch.E);  
adot  = (ch.infa(ch.alphaa(V,ion),ch.betaa(V,ion),V) - ch.m)/ch.taua(ch.alphaa(V,ion),ch.betaa(V,ion),V);
idot  = (ch.infi(ch.alphai(V,ion),ch.betai(V,ion),V) - ch.h)/ch.taui(ch.alphai(V,ion),ch.betai(V,ion),V);

As noted in this thread it's the use of anonymous functions aka fun = @(x) x; that makes it so. What can I do to make it faster? (Note I am solving an ODE with those, so they are called thousands times).

Two possible concerns you might have.

  1. I do have lots of dummy functions and variables there. Ion or V are not always used. Sometimes channel.na or channel.ni are zero, so there is no need to call any functions. I need those for the sake of generality and simplicity.
  2. I can get rid of alpha and beta functions by doing
    infaNEW = @(V,ion)
    ch.infa(ch.alphaa(V,ion),ch.betaa(V,ion),V)
    This way I'll decrease the number of functions.

Both these enhancements are likely increasing performance 2 fold each, not 20 fold as anonymous functions are slowing me down. Maybe a more direct question: Is there a way to convert anonymous functions to the normal ones, maybe automatically printing them to .m files?

Was it helpful?

Solution

I have posted the same question Matlab Central. Walter Roberson has given a pretty good response that has increased the performance by the order of magnitude.

You can convert anonymous functions to regular functions, yes, but the overhead will not be much different. It is the function call overhead that is slowing you down, not the fact that the functions are anonymous.

If you have the Symbolic toolbox, you could pass symbolic V and ion into your formulas, getting out expressions with the various functions expanded "in place"; simplify() that to optimize it a little, and then use matlabFunction() to convert the symbolic expression into an single anonymous function.

syms V ion 
curr  = ch.area*ch.g*ch.m^ch.na*ch.h^ch.ni*(V-ch.E);
adot  = (ch.infa(ch.alphaa(V,ion),ch.betaa(V,ion),V) - h.m)/ch.taua(ch.alphaa(V,ion),ch.betaa(V,ion),V);
idot  = (ch.infi(ch.alphai(V,ion),ch.betai(V,ion),V) - ch.h)/ch.taui(ch.alphai(V,ion),ch.betai(V,ion),V);
triple = [curr,adot,idot];
triplefcn = matlabFunction(simplify(triple), 'vars', [V, ion]);

Now a call to triplefcn passing in actual V and ion will return an array with curr, adot, idot as the columns. (It will be vectorized, too, which your current expressions are not.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top