Wolfram mathematica 自重启MathKernel-在Mathematica中可能吗?

Wolfram mathematica 自重启MathKernel-在Mathematica中可能吗?,wolfram-mathematica,mathematica-frontend,Wolfram Mathematica,Mathematica Frontend,此问题来自最近的问题“” 我想知道,是否有可能以编程方式重新启动MathKernel,使当前前端进程连接到新的MathKernel进程,并在新的MathKernel会话中评估一些代码?我指的是“透明”重启,它允许用户继续使用前端,同时拥有新的MathKernel进程,其中包含来自先前内核的一些代码 这个问题的动机是想找到一种方法,在MathKernel占用太多内存时自动重新启动,而不中断计算。换句话说,计算应该在新的MathKernel进程中自动继续,而不与用户交互(但保持用户与Mathemat

此问题来自最近的问题“”

我想知道,是否有可能以编程方式重新启动MathKernel,使当前前端进程连接到新的MathKernel进程,并在新的MathKernel会话中评估一些代码?我指的是“透明”重启,它允许用户继续使用前端,同时拥有新的MathKernel进程,其中包含来自先前内核的一些代码


这个问题的动机是想找到一种方法,在MathKernel占用太多内存时自动重新启动,而不中断计算。换句话说,计算应该在新的MathKernel进程中自动继续,而不与用户交互(但保持用户与Mathematica交互的能力与最初一样)。关于在新内核中应该评估哪些代码的细节当然是针对每个计算任务的。我正在寻找一个通用的解决方案,如何自动继续计算。

您可以使用
Exit[]
以编程方式终止内核。当您下次尝试计算表达式时,前端(笔记本)将自动启动新内核


保存“以前内核中的一些代码”将更加困难。你必须决定你想保留什么。如果您认为要保留所有内容,那么重新启动内核就没有意义了。如果知道要保存哪些定义,可以在终止内核之前使用
DumpSave
将它们写入文件,然后使用
听起来像是CleanSlate的工作

<< Utilities`CleanSlate`;
CleanSlate[]

以下方法运行一个内核,用它自己的内核打开前端,然后关闭并重新打开,更新第二个内核

此文件是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"]
演示笔记本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[]]]

它的设置有点复杂,目前的形式取决于在关闭和重新启动第二个内核之前需要等待多长时间。

也许并行计算机器可以用于此?下面是一个粗略的设置,说明了这个想法:

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
  ]
要演示恢复机制,请打开并行内核状态窗口,并不时杀死子内核
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
  ]
需要[“子内核`LocalKernels`]
doSomeWork[]:={$KernelID,长度[Get[$resultFile]],RandomReal[]}
$resultFile=“/some/place/results.dat”;
完成任务[]:=
模块[{subkernel,initsub,resultSoFar={}
,initsub[]:=
(子内核=启动内核[LocalMachine[1]]
;分布式定义[“全局”]
)
;initsub[]
;而[Length[resultSoFar]<1000
,Put[resultSoFar,$resultFile]
;安静[ParallelEvaluate[doSomeWork[],子内核]]/。
{$Failed:>(打印@“哎哟!”;CloseKernels[subkernel];initsub[]))
,r:>附录[resultSoFar,r]
}
]
;闭核[子核]
;结果
]
昨天在Stack Exchange Mathematica聊天时,完全引用了:

在笔记本中,如果您有多个单元格,您可以将Quit单独放入一个单元格中,并设置此选项:

SetOptions[$FrontEnd, "ClearEvaluationQueueOnKernelQuit" -> False]
然后,如果上面和下面有一个单元格,并选择所有三个单元格进行计算,内核将退出,但前端计算队列将继续(并为最后一个单元格重新启动内核)


--Arnoud Buzing

当我运行一个长循环的CUDAFunction,并且CUDALink内存不足时,我有一个类似的要求(这里类似:)。即使使用最新的Mathematica 10.4版本,内存泄漏也没有改善。我在这里找到了一个解决方法,希望你能发现它有用。其思想是使用bash脚本多次调用Mathematica程序(以批处理模式运行),并从bash脚本中传递参数。以下是详细说明和演示(适用于Windows操作系统):

  • 要在Win_OS中使用bash脚本,您需要安装cygwin()
  • 将mathematica笔记本转换为软件包(.m),以便能够在脚本模式下使用。如果使用“另存为…”保存笔记本,所有命令都将转换为注释(Wolfram Research注意到了这一点),因此最好创建一个包(文件->新建包),然后将命令复制并粘贴到该包中
  • 使用Vi编辑器(而不是记事本或gedit)编写bash脚本
    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
      ]
    
    SetOptions[$FrontEnd, "ClearEvaluationQueueOnKernelQuit" -> False]
    
    str=$CommandLine;
    len=Length[str];
    Do[
    If[str[[i]]=="-start",
    start=ToExpression[str[[i+1]]];
    Pause[start];
    Print["Done in ",start," second"];
    ];
    ,{i,2,len-1}];
    
    #c:\cygwin64\bin\bash
    for ((i=2;i<10;i+=2))
    do
    math -script test.m -start $i
    done