5

第一個問題兩個怪效率問題

我已超時需要多長時間來計算下面的語句(其中V [X]是一個耗時的函數調用):

Alice  = Table[V[i],{i,1,300},{1000}]; 
Bob  = Table[Table[V[i],{i,1,300}],{1000}]^tr; 
Chris_pre = Table[V[i],{i,1,300}]; 
Chris  = Table[Chris_pre,{1000}]^tr; 

愛麗絲,鮑勃和克里斯是相同的基礎計算3種稍微不同的方式。我發現Chris的計算速度比Alice和Bob快1000倍。

愛麗絲計算速度降低1000倍並不奇怪,因爲天真地說,函數V必須比計算克里斯時多1000倍。但是Bob的速度真的很慢,因爲他的計算方式是與Chris的區別在於Chris除了存儲中間步驟Chris_pre外。

爲什麼鮑勃評估這麼慢?


第二個問題

假設我要編譯一個函數在數學形式的

f(x)=x+y 

,其中「y」爲固定在編譯時的恆定(但我不喜歡直接用代碼替換它的數字,因爲我希望能夠輕鬆地更改它)。如果y的實際值是y = 7.3,並且我定義了

f1=Compile[{x},x+y] 
f2=Compile[{x},x+7.3] 

然後f1運行比f2慢50%。當我編譯f1時,如何讓Mathematica用「7.3」代替「y」,這樣f1的運行速度與f2一樣快?


編輯:

我發現了一個醜陋的解決辦法對於第二個問題:

f1=ReleaseHold[Hold[Compile[{x},x+z]]/.{z->y}] 

必須有一個更好的辦法...

回答

5

你或許應該已經張貼這些作爲單獨的問題,但不用擔心!

問題一

愛麗絲的問題當然是你期望的。 Bob的問題在於Table的每個迭代的內部Table被評估一次。這是清晰可見的與跟蹤:

Trace[Table[Table[i, {i, 1, 3}], {3}]] 

{ 
Table[Table[i,{i,1,2}],{2}], 
{Table[i,{i,1,2}],{i,1},{i,2},{1,2}},{Table[i,{i,1,2}],{i,1},{i,2},{1,2}}, 
{{1,2},{1,2}} 
} 

換行增加了強調,並且是的,跟蹤的表輸出是有點怪異,但你可以看到它。顯然,Mathematica可以更好地優化這一點,知道外部表沒有迭代器,但無論出於何種原因,它都沒有考慮到這一點。只有克里斯你想要做什麼,但你可以改變鮑勃:

Transpose[Table[Evaluate[Table[V[i],{i,1,300}]],{1000}]] 

這看起來像它實際上是由兩個或兩個這樣的因素優於克里斯,因爲它沒有存儲中間結果。

問題二

有與評價一個簡單的解決方案,但我希望它不會與所有可能的功能工作進行編譯(即真要追究,即那些):

f1 = Compile[{x}, Evaluate[x + y]]; 

你也可以使用With

With[{y=7.3}, 
    f1 = Compile[{x}, x + y]; 
] 

或者如果y在別處定義,使用臨時:

y = 7.3; 
With[{z = y}, 
    f1 = Compile[{x}, x + z]; 
] 

我不是Mathematica的範圍和評估機制方面的專家,所以可能會有更好的方法,但希望其中的一個能爲您做到!

+0

哇,非常感謝!這正是我所期待的。 (我將確保在將來單獨發佈這樣的問題。) – 2010-05-01 17:54:22

+0

使用With With可能是解決問題二的最安全的方法,因爲它在對其身體進行任何評估之前都會進行真正的詞彙替換。 – 2010-05-05 05:10:06

+0

@邁克爾皮拉特:同意。如果你已經定義了'y',我建議使用快速和骯髒的方法進行評估,但臨時的額外變量肯定更安全。 – Cascabel 2010-05-06 14:26:25

1

第一個問題 您是否檢查過Chris_pre計算的輸出?你會發現它根本不是一個大矩陣,因爲你試圖將一箇中間結果存儲在一個模式中,而不是一個變量。改爲嘗試ChrisPre。然後所有的時間都是可比的。

第二個問題 編譯對它的使用有一些棘手的限制。一個問題是你不能引用全局變量。已經提出的With構造是圍繞這個建議的方式。如果您想了解更多關於編譯,請特德埃爾塞克的招數: http://www.verbeia.com/mathematica/tips/Tricks.html

+0

糟糕。在我的實際代碼中,我使用了一個可接受的變量名稱Chris1。在寫這篇文章時,我忘了下劃線不能用於Mathematica中的變量。 非常感謝您的聯繫。這看起來像一些好東西。 – 2010-05-01 17:58:05

2

你的第一個問題已經解釋過,但我想指出的是,ConstantArray引入數學 6來解決這個問題。在此之前,Table[expr, {50}]用於固定和變化的表達式。

自引入ConstantArray以來,迭代與重新評估以及表達式的簡單重複之間存在明顯的分離。你可以看到使用此行爲:

ConstantArray[Table[Pause[1]; i, {i, 5}], {50}] ~Monitor~ i 

它需要五秒鐘遍歷Table因爲Pause[1],但之後循環完成它不是重新評估並在50個副本立即打印。