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