2009-08-21 172 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