使用匿名函数瓶颈提高 matlab 代码的性能

Posted

技术标签:

【中文标题】使用匿名函数瓶颈提高 matlab 代码的性能【英文标题】:improving performance of matlab code with anonymous-function bottlenecks 【发布时间】:2011-10-28 16:17:44 【问题描述】:

我在 matlab 2011a 中遇到了匿名函数的严重性能问题,其中匿名容器函数引入的开销远远大于封闭函数本身所花费的时间。

我阅读了几个相关问题,用户在这些问题中很有帮助地解释说这是其他人遇到的问题,表明我可以通过取消匿名容器来显着提高性能。不幸的是,我的代码的结构方式让我不确定如何在不破坏很多东西的情况下做到这一点。

那么,是否有一些变通方法可以在不完全取消匿名函数的情况下提高它们的性能,或者是否有设计模式可以让我在不使代码臃肿和花费大量时间重构的情况下取消匿名函数?

一些可能有帮助的细节:

下面是匿名函数的集合,它们存储为类属性。原则上,使用由 switch 语句使用的 int 数组可以替换数组,但 GP 的内容可能会发生变化——还有其他函数与 traingps 具有相同的参数结构,可以在那里使用——和GP 的内容在某些情况下可能会在运行时确定。

m3.GPs = @(X,ytrain,xStar,noisevar,params)traingp(X,ytrain,xStar,noisevar,1,params,[1  0]');
       @(X,ytrain,xStar,noisevar,params)traingp(X,ytrain,xStar,noisevar,1,params,[-1 1]');
       @(X,ytrain,xStar,noisevar,params)traingp(X,ytrain,xStar,noisevar,2,params,0);
       @(X,ytrain,xStar,noisevar,params)traingp(X,ytrain,xStar,noisevar,3,params,0);
       @(X,ytrain,xStar,noisevar,params)traingp(X,ytrain,xStar,noisevar,4,params,[0 0 0]');

稍后,GP 的元素由类的成员函数调用,如下所示:

GPt = GPst(j)(xj,yj,gridX(xi),thetaT(1),thetaT(2:end));

根据分析器,匿名包装器的自用时间占总时间的 95%(44 次调用为 1.7 秒!),而包含函数则为 5%。我在其他地方使用了类似的方法,按比例而言,匿名包装器的成本甚至更高。

是否有人对如何减少匿名调用的开销有任何想法,或者,如果没有,如何在保留匿名函数提供的灵活性的同时替换匿名函数(并且不引入一堆额外的簿记和参数传递)?

谢谢!

【问题讨论】:

为什么不将整数和数组添加到参数中?我认为这个问题可以通过使用一个以该数组的索引作为参数的函数来避免函数数组来简化很多。 @ChrisLucas:你能想出一个我们可以自己测试的最小工作示例吗? @stardt:不幸的是,我真的想保留泛化到具有相同参数结构的其他未知函数可以替换给定函数的情况的能力,可能在运行时。如果有办法在消除函数数组的同时做到这一点,我很乐意尝试一下。 @amro:我会在会议回来后尽快尝试这样做。相关代码不易提取,但看起来确实很有价值。 @ChrisLucas 我已经发布了一种更改函数参数结构的方法,但这并不能真正回答您的问题。 【参考方案1】:

这一切都取决于您愿意忍受多少痛苦来提高性能。这是避免匿名函数的一个技巧。我不知道它会如何为您介绍。我相信您可以将这些“小”函数放在类文件的末尾(我知道您可以将它们放在常规函数文件的末尾。)

function [output] = GP1(x,ytrain,xstar,noisevar,params)
   output = traingp(X,ytrain,xStar,noisevar,1,params,[1  0]);
end
...

m3.GPS = @GP1, @GP2, ...; 

【讨论】:

【参考方案2】:

也许函数“工厂”会有所帮助:

>> factory = @(a,b,c) @(x,y,z) a*x+b*y+c*z;
>> f1 = factory(1,2,3);
>> f2 = factory(0,1,2);
>> f1(1,2,3)
ans =
    14
>> f1(4,5,6)
ans =
    32
>> f2(1,2,3)
ans =
     8
>> f2(4,5,6)
ans =
    17

这里,factory 是一个返回具有不同参数的新函数的函数。另一个例子可能是:

 factory = @(a,b,c) @(x,y,z) some_function(x,y,z,a,b,c)

它返回一个x,y,z 指定a,b,c 的函数。

【讨论】:

以上是关于使用匿名函数瓶颈提高 matlab 代码的性能的主要内容,如果未能解决你的问题,请参考以下文章

Matlab Codegen:不支持匿名函数

匿名函数中的Matlab大行

匿名函数

匿名函数,向量化和预分配,函数的函数,P码文件

在具有 GPU 加速的 arrayfun 中使用匿名函数 (Matlab)

添加匿名函数 matlab