12

この質問は、最近の質問「Mathematicaのメモリ使用量を制限する正しい方法は? 」から来ています。

現在の FrontEnd プロセスを新しい MathKernel プロセスに接続したまま、MathKernel をプログラムで再起動し、新しい MathKernel セッションでいくつかのコードを評価することは可能でしょうか? 以前のカーネルからのコードが評価/評価されている新しい新しい MathKernel プロセスを使用しながら、ユーザーがフロントエンドでの作業を続行できるようにする「透過的な」再起動を意味しますか?

この質問の動機は、MathKernel が大量のメモリを消費する場合に、計算を中断することなく、MathKernel の再起動を自動化する方法を用意することです。言い換えれば、計算は、ユーザーとの対話なしに、新しいMathKernelプロセスで自動的に続行する必要があります(ただし、ユーザーがMathematicaと対話する機能は元のように維持されます)。もちろん、新しいカーネルでどのコードを評価する必要があるかについての詳細は、各計算タスクに固有です。計算を自動的に続行する一般的な解決策を探しています。

4

6 に答える 6

9

昨日のArnoudBuzingのコメントから、Stack Exchange Mathematicaチャットで、完全に引用しています。

ノートブックでは、複数のセルがある場合、Quitをセルに単独で配置し、次のオプションを設定できます。

SetOptions[$FrontEnd, "ClearEvaluationQueueOnKernelQuit" -> False]

次に、その上下にセルがあり、3つすべてを選択して評価すると、カーネルは終了しますが、フロントエンド評価キューは続行されます(最後のセルのカーネルを再起動します)。

--Arnoud Buzing

于 2012-12-06T09:29:39.577 に答える
5

次のアプローチでは、1 つのカーネルを実行して独自のカーネルでフロントエンドを開きます。フロントエンドは閉じられてから再度開かれ、2 番目のカーネルが更新されます。

このファイルは 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 には、次の 2 つのセルが含まれています。

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[]]]

最初のカーネルはフロントエンドを開き、最初のセルを実行します。その後、フロントエンドを終了し、再度開き、2 番目のセルを実行します。

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

セットアップは少し複雑で、現在の形式では、2 番目のカーネルを閉じて再起動するまでの待機時間を把握する必要があります。

于 2011-10-23T12:12:28.980 に答える
5

おそらく、並列計算機構はこれに使用できますか? 以下は、アイデアを説明する大まかなセットアップです。

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
  ]

これは、1,000 個の 3 つの数字のリストを生成するための、非常に手の込んだセットアップです。 getTheJobDone結果リストに必要な数の要素が含まれるまで続くループを実行します。ループの各反復は、サブカーネルで評価されます。サブカーネルの評価が失敗した場合、サブカーネルは再起動されます。それ以外の場合、その戻り値が結果リストに追加されます。

これを試すには、以下を評価します。

getTheJobDone[]

回復メカニズムを実証するために、[ Parallel Kernel Status ] ウィンドウを開き、時々サブカーネルを強制終了します。 getTheJobDone痛みを感じて印刷します痛い!サブカーネルが死ぬときはいつでも。ただし、全体的なジョブは続行され、最終結果が返されます。

ここでのエラー処理は非常に粗雑であり、実際のアプリケーションでは強化する必要があるでしょう。また、サブカーネルでの本当に重大なエラー状態 (メモリ不足など) がメイン カーネルに悪影響を与えるかどうかも調査していません。MemoryInUse[]もしそうなら、おそらくサブカーネルは、あらかじめ決められた閾値を超えた場合、自らを殺すことができます.

更新 - サブカーネルのクラッシュからメイン カーネルを分離する

このフレームワークをいじってみると、メイン カーネルとサブカーネルの間で共有変数を使用すると、サブカーネルがクラッシュした場合に Mathematica が不安定になることがわかりました。これには、DistributeDefinitions[resultSoFar]上記の の使用と、 を使用した明示的な共有変数も含まれますSetSharedVariable

この問題を回避するためにresultSoFar、ファイルを介して を送信しました。これにより、2 つのカーネル間の同期が取り除かれ、メイン カーネルがサブカーネル クラッシュをまったく認識しないという最終結果が得られました。また、メインのカーネル クラッシュが発生した場合にも中間結果を保持するという優れた副作用もありました。もちろん、サブカーネルの呼び出しもかなり遅くなります。しかし、サブカーネルへの各呼び出しがかなりの量の作業を実行する場合、それは問題にならないかもしれません。

改訂された定義は次のとおりです。

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
  ]
于 2011-10-29T06:12:28.757 に答える
3

長いループで CUDAFunction を実行し、CUDALink がメモリ不足になった場合にも同様の要件があります (ここで同様: https://mathematica.stackexchange.com/questions/31412/cudalink-ran-out-of-available-memory ) . 最新の Mathematica 10.4 バージョンでもメモリ リークは改善されません。ここで回避策を見つけて、それが役立つことを願っています。アイデアは、bash スクリプトを使用して、bash スクリプトからパラメータを渡して Mathematica プログラムを複数回呼び出す (バッチ モードで実行する) というものです。詳細な手順とデモは次のとおりです (これは Windows OS 用です)。

  • Win_OS で bash-script を使用するには、cygwin ( https://cygwin.com/install.html ) をインストールする必要があります。
  • Mathematica ノートブックをパッケージ (.m) に変換して、スクリプト モードで使用できるようにします。「名前を付けて保存..」を使用してノートブックを保存すると、すべてのコマンドがコメントに変換されます (これは Wolfram Research によって指摘されています)。そのため、パッケージを作成し (File->New-Package)、コピーして貼り付けることをお勧めします。それに対するあなたの命令。
  • 「\r」の問題を回避するために、Vi エディター (ウィンドウのメモ帳や gedit の代わりに) を使用して bash スクリプトを記述します ( http://www.linuxquestions.org/questions/programming-9/shell-scripts-in-windows- cygwin-607659/ )。

これは test.m ファイルのデモです

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}];

この Mathematica コードは、コマンドラインからパラメータを読み取り、それを計算に使用します。これは、さまざまなパラメーターで test.m を何度も実行するための bash スクリプト (script.sh) です。

#c:\cygwin64\bin\bash
for ((i=2;i<10;i+=2))
do
math -script test.m -start $i
done

Cygwin ターミナルで「chmod a+x script.sh」と入力してスクリプトを有効にすると、「./script.sh」と入力してスクリプトを実行できます。

于 2016-03-10T16:52:37.800 に答える
2

を使用して、プログラムでカーネルを終了できますExit[]。次に式を評価しようとすると、フロントエンド(ノートブック)は自動的に新しいカーネルを開始します。

「以前のカーネルの一部のコード」を保持することは、より困難になります。何を保存するかを決める必要があります。すべてを保持したい場合は、カーネルを再起動しても意味がありません。保存する定義がわかっている場合はDumpSave、カーネルを終了する前にそれらをファイルに書き込んでから、<<そのファイルを新しいカーネルにロードするために使用できます。

一方、どの定義がメモリを大量に消費しているかがわかっている場合は、、、、を使用してUnset、それらの定義を削除できます。$ HistoryLengthを(デフォルト)よりも小さい値に設定することもできます(それがメモリの目的である場合)。ClearClearAllRemoveInfinity

于 2011-10-23T06:29:59.513 に答える
0

CleanSlate の仕事のようですね。

<< Utilities`CleanSlate`;
CleanSlate[]

出典: http://library.wolfram.com/infocenter/TechNotes/4718/

「CleanSlate は、CleanSlate.m パッケージが最初にロードされたときの状態にカーネルを戻すために、可能な限りのことを試みます。」

于 2011-10-23T09:45:29.447 に答える