2009-08-21 171 views
3

我遇到了一些非常奇怪的计时行为,我写了一个函数。如果我将我的函数封装在另一个空容器函数中,它会获得3倍的加速比。MATLAB神奇的神秘计时行为

>> tic; FOO(参数); TOC

经过的时间:〜140秒

>>抽动;巴(参数); TOC

经过的时间:〜35秒

这里的起脚 - 巴()的定义:

限定巴(参数)

FOO(参数)

结束

是否存在某种针对嵌套函数调用在MATLAB中触发的优化?我应该为每个我写的函数添加一个虚拟函数吗?

+1

有几个问题:这是否可重复(即,您是否运行过多次)?什么是论据?是否有任何潜在的“名称冲突”(具有相同名称的变量和函数)? – gnovice 2009-08-21 18:18:02

+1

请发布一个简短但完整的函数集(如果您愿意的话)来演示此行为。这使得其他人更容易挖掘并试图找出问题所在。 – 2009-08-21 18:30:22

+0

当然,我会看看是否可以生成此行为可观察的最简单的程序和数据集。行为是可重复的。 我用很少的信息问,看看这种行为是否是由Matlab世界熟知的。 – 2009-08-21 19:06:54

回答

3

就我所知,JIT加速器不能在命令行表达式上运行。因此,当你运行“tic; foo(args); toc”foo的代码完全在MATLAB解释器中运行。然而,当你运行“tic; bar(args); toc”时,bar会在解释器中被评估,并且JIT加速器会在将foo()调用编译为本地代码时进行一些处理。

我真的在挥动手中的细节,但这是它的要点。 MATLAB的JIT功能的细节很难得到;我发现的大部分内容都在The MathWorks的Loren博客上。我可以找到关于命令行是解释器的最接近的权威声明: http://blogs.mathworks.com/loren/2006/05/10/memory-management-for-functions-and-variables/#comment-207

+0

我将此标记为答案,因为它听起来似乎很合理。 – 2010-03-29 03:07:17

1

您是否尝试过第二次而不清除变量?我无法重现这种性能提升如果我反复运行它。否则,它看起来更快,但这只是因为如果您运行一次,MATLAB会预编译这些函数。

function barfoo  

    for i = 1:Inf 
    end  

end 

而且,

function foobar   
    barfoo(); 
end 
1

我不知道你是否已经尝试运行代码多次,但我已经注意到了一个可能的解释是,新更新的文件的第一个运行通常比后续运行更慢(我假定由于编译)。我猜你可能会看到下面的第三行(修改后foo称呼)不同时间:

tic; foo(args); toc; % First call of foo 
tic; bar(args); toc; % Second call of foo inside bar 
tic; foo(args); toc; % Third call of foo 
+1

我可以根据需要多次运行foo和bar,我仍然可以获得100-140秒的foo和25-30秒的酒吧。 – 2009-08-21 19:09:19

1

这是令人惊讶的行为。中间函数调用不应该像这样加快速度。

尝试剖析它,看看它在哪里花费时间。这是几乎所有“为什么我的Matlab代码很慢?”的最佳第一手段?题。

clear all 
profile on -timer real 
foo(args); 
profile report 
%read the report and save a screencap 
clear all 
profile clear 
bar(args); 
profile report 

有结束的建议。这里开始猜测。

在两次调用中有几件事情是不同的。有工作区交互。从命令行调用foo()可能会在工作区中填充变量“ans”。当从bar()调用时,ans将被设置,但是当bar()返回时立即清除。此外,foo()可能会使用evalin()/ assignin()来查看调用堆栈中的工作空间,并且它可能会与基本工作空间中分配的变量进行交互。 bar()函数有一个干净的工作区。

取决于bar.m的位置,它可能实际上是调用不同的foo(),或者可能稍微不同地解析它。在上下文中用“which foo”来检查你的路径分辨率。

根据如何定义“args”,不同的inputname()对foo可能是可见的。此外,foo()可能包含病态代码,用于检查它是从基工作区调用的,还是由特定名称的函数调用它,并基于此行为有所不同。

也就是说,这些应该主要是次要的交互作用,不应该导致该顺序的放缓。我怀疑还有其他事情正在发生,也许只是略有不同的调用环境暴露出来。用bar()添加一个间接级别不应该是答案。了解分析器必须说的话并从那里开始。精确的代码重现将有助于从社区获得帮助。

+0

我很抱歉没有出现,这不是我的选择。使用你的建议,我可能能够将问题缩小到我可以分享的足够小的数量。谢谢! – 2009-08-27 19:59:14