有时,当我在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实现异步的评价?
我现在的工作,但它完全阻止任何进一步的用户输入。我不能只是设置,忘记和稍后检查。
有什么想法?
您精心描述`SafeEvaluate`但你花几句您的实际问题和我剩下的猜测它的意思。您是否正在寻找一种方法来评估一个单元格中的表达式,使评估运行并评估第二个单元格中的表达式,在第一个单元格的评估完成之前可能会得出结果? – 2011-12-15 08:55:21
@ Mr.Wizard这是我对这个问题的解读。我的第一个想法是,这是不可能的,因为任何评估都会改变内核状态。因此,两个并行的评估将模拟地改变内核状态:迈克实际上要求多线程,它带来了所有的困难和微妙之处。 (即使使用并行内核,一些状态也会被共享以获得结果。)但是后来我想到了Dynamic [f [i]]`,Table [Pause [1];我,{我,10}]`(尝试它 - 就像'监视器')。这实际上是在单个内核中并行地评估事物。 – Szabolcs 2011-12-15 09:13:02
@Szabolcs他说他想在单个内核中进行并行评估? – 2011-12-15 09:18:40