有时当我在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[Length@kernels != 0,
For[i = 1, i <= Length@kernels, i++,
If[kernels[[i, 1, 2]] > 0, Return@kernels[[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}]]
Mathematica会优雅地返回$Aborted
告诉你内存不足。通过在单独的内核中进行评估,我们可以将代码沙箱放入其自己的并行内核中。如果出现问题,那么我们的主内核不会受到影响。
这让我想到了我的要点:如何在Mathematica中实现异步评估?
我现在所拥有的功能,但它完全阻止了任何进一步的用户输入。我不能随便设置,忘记和检查。
有什么想法吗?
答案 0 :(得分:7)
我在Mathematica中几乎没有使用并行计算的经验,所以这可能不是最好的方法,但这是我设法挖掘的from the docs:
启动内核:
In[1]:= LaunchKernels[1]
Out[1]= KernelObject[1, "local"]
提交一些长期工作:
In[2]:= job =
ParallelSubmit[First@SingularValueList[RandomReal[1, {2000, 2000}]]]
开始工作:
In[3]:= Parallel`Developer`QueueRun[]
Out[3]= True
现在作业在后台并行运行......
...我们可以自由地在主内核中做任何我们想做的事情。如果我理解你的问题,这就是你需要的。我们可以再次运行Parallel`Developer`QueueRun[]
来检查哪些并行评估已完成(评估对象的显示将动态更新)。
In[4]:= 1 + 1
Out[4]= 2
等到评估结束(如果还没有)并收集结果:
In[5]:= WaitAll[job]
Out[5]= 1000.23
答案 1 :(得分:3)
经常发生的事情是你的系统会耗尽内存并开始交换。交换将使系统死亡缓慢。在Linux上这就是我做的事情
alias m804='ulimit -v 3800000; /usr/local/bin/math8.0.4/mathematica'
系统然后只是给出内存不足消息并在它进入交换之前退出。否则就像往常一样。
答案 2 :(得分:1)
我不认为这个功能在 9 年前被问到这个问题时就存在了。但是对于任何在 Mathematica 12 及更高版本中寻找解决方案的人,您只需使用 SessionSubmit[]
。因此,在这种情况下,您需要 SessionSubmit[SafeEvaluate[Table[{x, x}, {1024^3}]]].
SessionSubmit[]
函数创建一个新任务并在当前会话中异步运行它。或者,LocalSubmit[]
可用于在单独的内核中异步运行命令,因此在较新版本的 Mathematica 中甚至不需要 SafeEvaluate 函数。可以在 SessionSubmit 和 LocalSubmit 的文档页面上找到更多信息。此外,阅读 Task Objects 的文档页面也可能很有用。
答案 3 :(得分:0)
很久以前,我使用过Mathematica,但我有一个想法。据我所知,您可以在加载Mathematica文档时设置功能的自动评估。无法使用Mathematica创建一个文档,其SafeEvaluate [function]为“run on loading”,并在后台使用此文档启动另一个Mathematica流程。然后你仍然可以使用你看到的输入。当然,那么你必须汇集该进程以查看它是否结束,或者让评估的函数保存您汇集的结果文件。