Ale*_*kov 9 wolfram-mathematica mathematica-frontend
这个问题来自最近的问题" 正确的方法来限制Mathematica内存使用? "
我想知道,是否有可能以编程方式重新启动MathKernel,使当前的FrontEnd进程连接到新的MathKernel进程并在新的MathKernel会话中评估一些代码?我的意思是"透明"重启,它允许用户继续使用FrontEnd,同时拥有新的MathKernel流程,其中一些代码来自之前评估/评估的内核?
这个问题的动机是有一种方法可以在不中断计算而占用太多内存的情况下自动重启MathKernel .换句话说,计算应该在新的MathKernel过程中自动继续,而不与用户交互(但保持用户与Mathematica最初交互的能力).在新内核中应该评估什么代码的细节当然是针对每个计算任务的.我正在寻找一个通用的解决方案如何自动继续计算.
根据Arnoud Buzing昨天的评论,在Stack Exchange Mathematica聊天中,完全引用:
在笔记本中,如果您有多个单元格,可以将Quit单独放入单元格中并设置此选项:
SetOptions[$FrontEnd, "ClearEvaluationQueueOnKernelQuit" -> False]
Run Code Online (Sandbox Code Playgroud)
然后,如果你上面和下面有一个单元格并选择全部三个并进行评估,则内核将退出,但前端评估队列将继续(并重新启动最后一个单元格的内核).
- Arnoud Buzing
以下方法运行一个内核来打开具有自己内核的前端,然后关闭并重新打开,更新第二个内核.
此文件是MathKernel输入,C:\ Temp\test4.m
Needs["JLink`"];
$FrontEndLaunchCommand="Mathematica.exe";
UseFrontEnd[
nb = NotebookOpen["C:\\Temp\\run.nb"];
SelectionMove[nb, Next, Cell];
SelectionEvaluate[nb];
];
Pause[8];
CloseFrontEnd[];
Pause[1];
UseFrontEnd[
nb = NotebookOpen["C:\\Temp\\run.nb"];
Do[SelectionMove[nb, Next, Cell],{12}];
SelectionEvaluate[nb];
];
Pause[8];
CloseFrontEnd[];
Print["Completed"]
Run Code Online (Sandbox Code Playgroud)
演示笔记本C:\ Temp\run.nb包含两个单元格:
x1 = 0;
Module[{},
While[x1 < 1000000,
If[Mod[x1, 100000] == 0, Print["x1=" <> ToString[x1]]]; x1++];
NotebookSave[EvaluationNotebook[]];
NotebookClose[EvaluationNotebook[]]]
Print[x1]
x1 = 0;
Module[{},
While[x1 < 1000000,
If[Mod[x1, 100000] == 0, Print["x1=" <> ToString[x1]]]; x1++];
NotebookSave[EvaluationNotebook[]];
NotebookClose[EvaluationNotebook[]]]
Run Code Online (Sandbox Code Playgroud)
初始内核打开前端并运行第一个单元格,然后退出前端,重新打开它并运行第二个单元格.
整个过程可以通过将MathKernel输入粘贴(一次性)到内核会话中运行,也可以从批处理文件运行,例如C:\ Temp\RunTest2.bat
@echo off
setlocal
PATH = C:\Program Files\Wolfram Research\Mathematica\8.0\;%PATH%
echo Launching MathKernel %TIME%
start MathKernel -noprompt -initfile "C:\Temp\test4.m"
ping localhost -n 30 > nul
echo Terminating MathKernel %TIME%
taskkill /F /FI "IMAGENAME eq MathKernel.exe" > nul
endlocal
Run Code Online (Sandbox Code Playgroud)
它的设置有点精心设计,它的当前形式取决于知道在关闭和重启第二个内核之前需要等待多长时间.
也许并行计算机可以用于此?这是一个粗略的设置,说明了这个想法:
Needs["SubKernels`LocalKernels`"]
doSomeWork[input_] := {$KernelID, Length[input], RandomReal[]}
getTheJobDone[] :=
Module[{subkernel, initsub, resultSoFar = {}}
, initsub[] :=
( subkernel = LaunchKernels[LocalMachine[1]]
; DistributeDefinitions["Global`"]
)
; initsub[]
; While[Length[resultSoFar] < 1000
, DistributeDefinitions[resultSoFar]
; Quiet[ParallelEvaluate[doSomeWork[resultSoFar], subkernel]] /.
{ $Failed :> (Print@"Ouch!"; initsub[])
, r_ :> AppendTo[resultSoFar, r]
}
]
; CloseKernels[subkernel]
; resultSoFar
]
Run Code Online (Sandbox Code Playgroud)
这是一个过于复杂的设置,用于生成 1,000 个数字三元组的列表。 getTheJobDone运行一个循环,直到结果列表包含所需数量的元素。循环的每次迭代都在子内核中进行评估。如果子内核评估失败,则重新启动子内核。否则,将其返回值添加到结果列表中。
要尝试此操作,请评估:
getTheJobDone[]
Run Code Online (Sandbox Code Playgroud)
要演示恢复机制,请打开Parallel Kernel Status窗口并不时终止子内核。 getTheJobDone会感到疼痛并打印哎哟!每当子内核死亡时。但是,整个作业会继续并返回最终结果。
这里的错误处理非常粗糙,可能需要在实际应用中得到支持。此外,我还没有调查子内核中真正严重的错误情况(如内存不足)是否会对主内核产生不利影响。如果是这样,那么子内核可能会在MemoryInUse[]超过预定阈值时杀死自己。
更新 - 将主内核与子内核崩溃隔离
在玩这个框架时,我发现如果子内核崩溃,主内核和子内核之间共享变量的任何使用都会导致 Mathematica 不稳定。这包括使用DistributeDefinitions[resultSoFar]如上所示,以及显式共享变量使用SetSharedVariable.
为了解决这个问题,我resultSoFar通过一个文件传输。这消除了两个内核之间的同步,最终结果是主内核仍然幸福地不知道子内核崩溃。它还具有在主内核崩溃时保留中间结果的良好副作用。当然,这也使得子内核调用慢了很多。但如果每次调用子内核都执行大量工作,那可能就不是问题。
以下是修订后的定义:
Needs["SubKernels`LocalKernels`"]
doSomeWork[] := {$KernelID, Length[Get[$resultFile]], RandomReal[]}
$resultFile = "/some/place/results.dat";
getTheJobDone[] :=
Module[{subkernel, initsub, resultSoFar = {}}
, initsub[] :=
( subkernel = LaunchKernels[LocalMachine[1]]
; DistributeDefinitions["Global`"]
)
; initsub[]
; While[Length[resultSoFar] < 1000
, Put[resultSoFar, $resultFile]
; Quiet[ParallelEvaluate[doSomeWork[], subkernel]] /.
{ $Failed :> (Print@"Ouch!"; CloseKernels[subkernel]; initsub[])
, r_ :> AppendTo[resultSoFar, r]
}
]
; CloseKernels[subkernel]
; resultSoFar
]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3343 次 |
| 最近记录: |