如何在Matlab中制作和使用许多快速函数?

时间:2013-12-26 15:25:40

标签: performance matlab anonymous-function

Hello大地的搭便车员,我刚刚发现Matlab中的匿名函数有多慢。但是,我找不到方便的替代方案。我需要生成大约12个这样的通道,每个通道都有8个小功能。这是一个例子。

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];

这一代不是问题。但我想使用这些函数,以下代码使它非常慢。

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);

正如本thread所述,使用匿名函数aka fun = @(x) x;就是这样。 我可以做些什么来加快速度?(注意我正在用这些来解决ODE,所以它们被称为数千次)。

您可能有两种可能的担忧。

  1. 我确实有很多虚拟函数和变量。不总是使用Ion或V.有时channel.na或channel.ni为零,因此无需调用任何函数。为了普遍性和简洁性,我需要那些。
  2. 我可以通过执行infaNEW = @(V,ion)
    ch.infa(ch.alphaa(V,ion),ch.betaa(V,ion),V)来摆脱alpha和beta功能。这样我就可以减少功能数量。
  3. 这些增强功能可能每次增加2倍,而不是20倍,因为匿名功能正在减慢我的速度。也许是一个更直接的问题:有没有办法将匿名函数转换为普通函数,可能会自动将它们打印到.m文件中?

1 个答案:

答案 0 :(得分:1)

I have posted the same question Matlab Central. Walter Roberson给出了相当不错的响应,使性能提高了数量级。

  

您可以将匿名函数转换为常规函数,是的,但开销不会有太大差异。函数调用开销会降低你的速度,而不是函数是匿名的。

     

如果您有符号工具箱,则可以传递符号V和离子   进入你的公式,用各种函数表达出来   扩展"到位&#34 ;;简化(),以便稍微优化它,然后   使用matlabFunction()将符号表达式转换为单个表达式   匿名函数。

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]);
     

现在调用triplefcn传递实际V和离子将   返回一个以curr,adot,idot为列的数组。 (这将是   矢量化,你当前的表达式也不是。)