2011-12-15 88 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' 

然后系统只是给出内存不足的消息并在交换之前退出。否则就像平常一样行事。