2011-12-15 85 views
9

有時,當我在Mathematica中編寫實驗代碼時,我很擔心我是否應該評估它,因爲它可能最終導致我的系統屈服於膝蓋。Mathematica中的異步評估

作爲一個人爲的例子,如果您嘗試在64位機器上運行以下代碼片段,它很可能會導致您的系統在耗盡所有內存後磨碎到完全停止。

junk = Table[{x, x}, {10^9}]; (* nom nom nom memory. Please don't run this. *) 

當然,你可以只是把MemoryConstrained到它,並希望最好的,但有時你不希望它阻止任何進一步的輸入。爲此,我認爲最好能夠實現中間立場的方式是在單獨的內核中進行評估。

這是體面很容易的做到:

ClearAll[GetAvailableKernel]; 
GetAvailableKernel[] := Block[{i, kernels}, 
    kernels = Kernels[]; 
    If[[email protected] != 0, 
    For[i = 1, i <= [email protected], i++, 
    If[kernels[[i, 1, 2]] > 0, [email protected][[i]]] 
    ] 
    ]; 
    LaunchKernels[1]] 

ClearAll[SafeEvaluate]; 
SetAttributes[SafeEvaluate, HoldFirst]; 
Options[SafeEvaluate] = {"EvaluationKernel" -> Null, 
    "ConstrainMemory" -> True, "MaxMemory" -> 2 1024^3}; 

SafeEvaluate[expr_, OptionsPattern[]] := Block[{evalkernel, result}, 
    If[OptionValue["EvaluationKernel"] != Null, 
    evalkernel = OptionValue["EvaluationKernel"], 
    evalkernel = GetAvailableKernel[] 
    ]; 

    result = If[OptionValue["ConstrainMemory"], 
    With[{memory = OptionValue["MaxMemory"]}, 
    ParallelEvaluate[MemoryConstrained[expr, memory], evalkernel]], 
    ParallelEvaluate[expr, evalkernel]]; 
    result] 

然後,你可以先走一步,做線沿線的東西:

SafeEvaluate[Table[{x, x}, {1024^3}]] 

而且數學會優雅地恢復$Aborted告訴你,它跑了內存不足。通過在單獨的內核中進行評估,我們可以將代碼存儲到它自己的並行內核中。如果出現問題,那麼我們的主內核不受影響。


這引出了我的主要觀點:我怎樣才能在Mathematica實現異步的評價?

我現在的工作,但它完全阻止任何進一步的用戶輸入。我不能只是設置,忘記和稍後檢查。

有什麼想法?

+0

您精心描述`SafeEvaluate`但你花幾句您的實際問題和我剩下的猜測它的意思。您是否正在尋找一種方法來評估一個單元格中的表達式,使評估運行並評估第二個單元格中的表達式,在第一個單元格的評估完成之前可能會得出結果? – 2011-12-15 08:55:21

+0

@ Mr.Wizard這是我對這個問題的解讀。我的第一個想法是,這是不可能的,因爲任何評估都會改變內核狀態。因此,兩個並行的評估將模擬地改變內核狀態:邁克實際上要求多線程,它帶來了所有的困難和微妙之處。 (即使使用並行內核,一些狀態也會被共享以獲得結果。)但是後來我想到了Dynamic [f [i]]`,Table [Pause [1];我,{我,10}]`(嘗試它 - 就像'監視器')。這實際上是在單個內核中並行地評估事物。 – Szabolcs 2011-12-15 09:13:02

+0

@Szabolcs他說他想在單個內核中進行並行評估? – 2011-12-15 09:18:40

回答

7

我旁邊,在數學並行計算零經驗,所以這可能不是最好的方式,但是這是我設法挖from the docs

啓動內核:

In[1]:= LaunchKernels[1] 

Out[1]= KernelObject[1, "local"] 

提交一些長期才能完成的工作:

In[2]:= job = 
ParallelSubmit[[email protected][RandomReal[1, {2000, 2000}]]] 

Mathematica graphics

開始工作:

In[3]:= Parallel`Developer`QueueRun[] 

Out[3]= True 

現在的工作是在後臺並行運行...

Mathematica graphics

...我們可以自由地做任何我們想做的主核心。如果我理解你的問題,這就是你需要的。我們可以再次運行Parallel`Developer`QueueRun[]來檢查哪些並行評估已完成(評估對象的顯示將動態更新)。

In[4]:= 1 + 1 

Out[4]= 2 

等到評估結束(如果還沒有),並收集結果:

In[5]:= WaitAll[job] 

Out[5]= 1000.23 

Mathematica graphics

0

很久以前,我用Mathematica,但我有一個想法。據我所知,您可以在加載Mathematica文檔時設置功能的自動評估。使用Mathematica創建一個SafeEvaluate [函數]文件作爲「加載時運行」並使用此文檔在後臺啓動另一個Mathematica進程是不可能的。那麼你仍然可以使用你看到的輸入。當然,那麼你將不得不將這個過程集中起來,看看它是否結束,或者讓評估的函數保存一個結果文件。

3

很多時候會發生什麼情況是您的系統將耗盡內存並開始交換。而交換會使系統死亡緩慢。在Linux上,這裏是我所做的

alias m804='ulimit -v 3800000; /usr/local/bin/math8.0.4/mathematica' 

然後系統只是給出內存不足的消息並在交換之前退出。否則就像平常一樣行事。