哪种类型的函数调用在MATLAB中提供更好的性能?gydF4y2Ba

203次浏览(过去30天)gydF4y2Ba
MathWorks支万博1manbetx援小组gydF4y2Ba
我有7种不同类型的函数调用:gydF4y2Ba
1.内联函数,代码作者将函数调用替换为函数体的副本。gydF4y2Ba
2.函数在单独的MATLAB文件中定义。参数由调用函数传递(file-pass)。gydF4y2Ba
3.函数在单独的MATLAB文件中定义。参数通过引用全局变量来提供;调用函数(file-global)只提供索引。gydF4y2Ba
4.嵌套函数。参数由外围函数传递(nest-pass)。gydF4y2Ba
5.嵌套函数。实参是与封闭函数共享的实参;只有索引是由封闭函数(nest-share)提供的。gydF4y2Ba
6.子函数。参数由调用函数传递(子传递)。gydF4y2Ba
7.子函数。参数通过引用全局变量来提供;调用函数只提供索引(sub-global)。gydF4y2Ba
(要了解更多信息,请参阅以下三个MATLAB文件:testTop。m、testCompute、testComputeGlobal.m)gydF4y2Ba
我想知道哪个函数调用通常比其他函数调用提供更好的性能。gydF4y2Ba

接受的答案gydF4y2Ba

MathWorks支万博1manbetx援小组gydF4y2Ba
编辑:gydF4y2BaMathWorks支万博1manbetx援小组gydF4y2Ba 2018年10月5日gydF4y2Ba
每个函数调用的性能从最快到最慢的顺序如下:gydF4y2Ba
inline > file-pass = nest-pass = sub-pass > nest-share > sub-global > file-globalgydF4y2Ba
(A>B表示A比B快,A=B表示A和B一样快)gydF4y2Ba
首先,使用内联函数是最快的,因为它不会引起与函数调用相关的开销。gydF4y2Ba
其次,当实参传递给被调用方函数时,调用方函数以被调用方函数知道在哪里检索实参的方式设置实参。这种与函数调用相关的设置通常会引起性能开销,因此文件传递、嵌套传递和子传递比内联传递慢。gydF4y2Ba
第三,如果工作空间与嵌套函数共享,并且嵌套函数的参数是在工作空间内共享的,而不是值传递,那么该函数调用的性能将受到抑制。如果MATLAB在共享工作空间中看到一个共享变量,它就会在工作空间中搜索该变量。另一方面,如果参数是由调用函数传递的,那么MATLAB就不需要搜索它们。这种搜索所花费的时间解释了type nest-share比file-pass、nest-pass和sub-pass要慢。gydF4y2Ba
最后,当函数调用涉及全局变量时,性能会受到更大的限制。这是因为为了寻找全局变量,MATLAB必须将其搜索空间扩展到当前工作空间的外部。此外,涉及全局变量的函数调用比其他函数调用慢得多的原因是MATLAB Accelerator没有优化这样的函数调用。当使用以下命令关闭MATLAB加速器时,gydF4y2Ba
功能gydF4y2Baaccel掉gydF4y2Ba
内联和文件-全局之间的性能差异变得不那么显著。gydF4y2Ba
请注意,这些行为在很大程度上取决于各种因素,如操作系统、CPU体系结构、MATLAB解释器和MATLAB代码正在做什么。gydF4y2Ba
1评论gydF4y2Ba
沃尔特·罗伯森gydF4y2Ba
沃尔特·罗伯森gydF4y2Ba 2018年7月5日gydF4y2Ba
还要注意,匿名函数调用比直接函数调用慢,但在几乎相同的代码中,差异可以从几乎可以忽略不计到相当大。gydF4y2Ba
(我有一些几年前组合在一起的测试用例,但我的系统目前正在加载,所以我现在不能进行定时测试。)gydF4y2Ba

登录评论。gydF4y2Ba

更多答案(6)gydF4y2Ba

罗伯特。gydF4y2Ba
罗伯特。gydF4y2Ba 2018年7月3日gydF4y2Ba
有用的东西,但第一个选项不应该是“1”。内联函数。函数体为gydF4y2Ba 直接gydF4y2Ba 写下来(内联)。”gydF4y2Ba
1评论gydF4y2Ba
Harsha PhadkegydF4y2Ba
Harsha PhadkegydF4y2Ba 2018年7月5日gydF4y2Ba
谢谢你指出错误,我们已经相应地更新了问题。gydF4y2Ba

登录评论。gydF4y2Ba


汉斯·GreimgydF4y2Ba
汉斯·GreimgydF4y2Ba 2015年3月31日gydF4y2Ba
一旦代码被编译并与MCR一起运行,答案会改变吗?gydF4y2Ba
1评论gydF4y2Ba
Rutuja ShiraligydF4y2Ba
Rutuja ShiraligydF4y2Ba 2015年7月7日gydF4y2Ba
一旦代码被编译并使用MCR运行,答案仍然保持不变。这是因为MATLAB编译器通过在安装的运行时上运行相同的MATLAB代码(尽管加密)来工作,并且不改变代码的性质。因此,编译后的MATLAB代码将以类似于在MATLAB桌面上运行的速度运行。gydF4y2Ba

登录评论。gydF4y2Ba


多米尼克gydF4y2Ba
多米尼克gydF4y2Ba 2020年6月13日gydF4y2Ba
编辑:gydF4y2Ba沃尔特·罗伯森gydF4y2Ba 2021年8月7日gydF4y2Ba
你好,gydF4y2Ba
我在看你的gydF4y2Ba 评论gydF4y2Ba 关于使用全局变量gydF4y2Ba 被期望gydF4y2Ba 总是放慢任何代码的运行时间。gydF4y2Ba
请检查以下代码,在R2019b上运行。gydF4y2Ba
在这里,您可以看到,使用全局变量可以使代码加快超过gydF4y2Ba 百的因数。gydF4y2Ba
使用全局变量gydF4y2Ba
运行时间为0.001173秒。gydF4y2Ba
传递变量gydF4y2Ba
运行时间为0.880516秒。gydF4y2Ba
请给我解释一下这是怎么回事!gydF4y2Ba
谢谢你gydF4y2Ba 的帮助,gydF4y2Ba
= = >gydF4y2Ba
n = 500000;gydF4y2Ba
全球gydF4y2Ba一个gydF4y2Ba
= 0 (100 n);gydF4y2Ba
b = 0 (100 n);gydF4y2Ba
%使用全局变量gydF4y2Ba
disp (gydF4y2Ba“使用全局变量”gydF4y2Ba)gydF4y2Ba
抽搐gydF4y2Ba
为gydF4y2Bai = 1:10 0gydF4y2Ba
t = test1;gydF4y2Ba
结束gydF4y2Ba
tocgydF4y2Ba
做同样的事情,将变量传递给函数gydF4y2Ba
disp (gydF4y2Ba传递变量的gydF4y2Ba)gydF4y2Ba
抽搐gydF4y2Ba
为gydF4y2Bai = 1:10 0gydF4y2Ba
t = test2 (b(我,:));gydF4y2Ba
结束gydF4y2Ba
tocgydF4y2Ba
使用全局变量时调用函数gydF4y2Ba
函数gydF4y2Bat = test1gydF4y2Ba
全球gydF4y2Ba一个gydF4y2Ba
t = (1);gydF4y2Ba
结束gydF4y2Ba
传递变量时调用函数gydF4y2Ba
函数gydF4y2Bat = test2 (x)gydF4y2Ba
t = x (1);gydF4y2Ba
结束gydF4y2Ba
3评论gydF4y2Ba
史蒂文的主gydF4y2Ba
史蒂文的主gydF4y2Ba 2020年6月15日gydF4y2Ba
供参考,如果你传递一个大变量到你的函数,但只有gydF4y2Ba 读gydF4y2Ba 它(不要试图复制它,也不要试图修改它)然后gydF4y2Ba 写时复制gydF4y2Ba MATLAB的行为可以避免在函数工作区中复制。gydF4y2Ba

登录评论。gydF4y2Ba


克里斯蒂安·勒gydF4y2Ba
克里斯蒂安·勒gydF4y2Ba 2021年1月26日gydF4y2Ba
与gydF4y2Ba 内联gydF4y2Ba 目前标记为gydF4y2Ba 不被看好gydF4y2Ba ,匿名函数的性能是否与gydF4y2Ba 内联gydF4y2Ba 现在好些了吗?gydF4y2Ba
假设我有两个调用,就像这个例子:gydF4y2Ba
A = 1;gydF4y2Ba
B = 2;gydF4y2Ba
f(x,a,b);gydF4y2Ba
根据需要替换变量gydF4y2Ba
F_in = inline(sprintf(gydF4y2Baf (x) % d % d)”gydF4y2Ba, a, b),gydF4y2Ba“x”gydF4y2Ba);gydF4y2Ba
%当用作包装器函数时更好,例如。gydF4y2Ba
Y = ode45(@f_an,.);gydF4y2Ba
%或gydF4y2Ba
Y = ode45(@f_in,..);gydF4y2Ba
函数gydF4y2BaY = f(x,a,b)gydF4y2Ba
多次调用主函数gydF4y2Ba
结束gydF4y2Ba
在这个例子中,它们是等价的,还是最好的实现仍然调用嵌套函数?gydF4y2Ba
当我们使用c++接口函数(自定义生成与gydF4y2Ba clibgengydF4y2Ba )?gydF4y2Ba
11日评论gydF4y2Ba
克里斯蒂安·勒gydF4y2Ba
克里斯蒂安·勒gydF4y2Ba 2021年1月27日gydF4y2Ba
问题在于gydF4y2Ba clibgengydF4y2Ba 生成的类和函数是它们不生成gydF4y2Ba .m 可编辑的文件。我可以举一个我正在做的更实际的例子:gydF4y2Ba
对于这个,我试着计算gydF4y2Ba fmincongydF4y2Ba 目标和约束取自c++接口。我们只考虑约束条件gydF4y2Ba
// c++代码:gydF4y2Ba
无效gydF4y2Ba类::nonlcon(double* x, double* c, int n_x, int n_c){gydF4y2Ba
//指定cgydF4y2Ba值在这里gydF4y2Ba
...gydF4y2Ba
}gydF4y2Ba
在构建类和方法之后,我们只有以下接口方法:gydF4y2Ba
% Matlab侧:gydF4y2Ba
首先需要构造对象gydF4y2Ba
obj = clib. projj .class();gydF4y2Ba
接口方法:gydF4y2Ba
N_c = 2;gydF4y2Ba
X = [1;2;3;4];gydF4y2Ba
C = obj.nonlcon(x,n_c);gydF4y2Ba
现在如果我们想把它应用到gydF4y2Ba fmincongydF4y2Ba 我们必须传递这个值gydF4y2Ba n_cgydF4y2Ba 也在这种情况下,我们不能使用文件函数,因为必须为要定义的方法创建对象。如果该方法是静态的,那么是的,该方法将同样有效。gydF4y2Ba
我发现的另一点是,当我们使用语法gydF4y2Ba @obj.nonlcongydF4y2Ba 时,该函数被作为匿名函数调用,而不是作为gydF4y2Ba function_handlegydF4y2Ba ,但我想这是有意义的,因为对象也必须被传递。如果有什么方法可以改进这部分,我洗耳恭听。gydF4y2Ba

登录评论。gydF4y2Ba


broken_arrowgydF4y2Ba
broken_arrowgydF4y2Ba 2021年3月20日gydF4y2Ba
这让我有点困惑。内联函数不就是将函数代码粘贴到脚本中吗(这意味着脚本应该是性能最好的)?另一方面,这篇文章表明函数通常比脚本快:gydF4y2Ba https://de.mathworks.com/matlabcentral/answers/415728-details-on-why-functions-are-faster-than-scriptsgydF4y2Ba 但是如果我将变量传递给一个函数,程序仍然必须在基本工作空间中查找变量并启动函数,这与脚本相比产生了开销。我的“工作假设”曾经是,所有只执行一次的东西都放在脚本中,函数是用于经常使用的代码……gydF4y2Ba
23日评论gydF4y2Ba
布鲁诺陈德良gydF4y2Ba
布鲁诺陈德良gydF4y2Ba 2021年3月24日gydF4y2Ba
我自己对这种描述的解读是gydF4y2Ba
  • 旧的JIT被分离到EE中,包括调用预构建库来取代MATLAB代码,gydF4y2Ba
  • 新的JIT集成到EE中,接近于对本机机器指令的编译。gydF4y2Ba

登录评论。gydF4y2Ba


查尔斯静gydF4y2Ba
查尔斯静gydF4y2Ba 2022年3月5日gydF4y2Ba
在新版本的MATLAB中,文档显示“内联”gydF4y2Ba 不建议使用。使用gydF4y2Ba 匿名函数gydF4y2Ba 相反。”gydF4y2Ba
1评论gydF4y2Ba
沃尔特·罗伯森gydF4y2Ba
沃尔特·罗伯森gydF4y2Ba 2022年3月5日gydF4y2Ba
您混淆了inline()函数与“内联”的概念。它们不是一回事,尽管它们有相似的名字。请阅读前面的讨论gydF4y2Ba //www.tianjin-qmedu.com/matlabcentral/answers/99537-which-type-of-function-call-provides-better-performance-in-matlab#answer_606428gydF4y2Ba
内联()gydF4y2Ba 作为一种功能已经被劝阻多年了。gydF4y2Ba

登录评论。gydF4y2Ba

社区寻宝gydF4y2Ba

在MATLAB Central中找到宝藏,并发现社区如何帮助您!gydF4y2Ba

开始狩猎!gydF4y2Ba