4

LinkClose[link]ドキュメントに記載されているように、「接続の反対側で必ずしもプログラムを終了するとは限りません」。スレーブ カーネルのプロセスを安全に強制終了する方法はありますか?

編集:

実際には、スレーブカーネルのプロセスがすでに終了し、そのメモリがすでに解放されている場合にのみ戻るMathematicaの関数が必要です。と の両方が、スレーブ カーネルが終了するまで待機LinkInterrupt[link, 1]LinkClose[link]ません。現時点では、そのような機能はkillProc[procID]、このページの回答の1つで示した機能だけのようです。しかし、内蔵のアナログはありますか?

4

2 に答える 2

1

Todd Gayley がニュースグループで私の質問に答えてくれました。解決策は、スレーブ カーネルにMLTerminateMessage. トップレベルのコードから:

   LinkInterrupt[link, 1] (* An undocumented form that lets you pick 
the message type *)

C:

   MLPutMessage(link, MLTerminateMessage);

J/Link を使用した Java の場合:

   link.terminateKernel();

.NET/Link を使用する .NET の場合:

   link.TerminateKernel();

編集:

私のオペレーティング システム (現時点では Windows 2000) を使用する標準的なケースでは、0.01 から 0.03 秒で物理メモリを解放するwhileLinkInterrupt[link, 1] の実行の瞬間から始まる 0.05 から 0.1 秒でのみ物理メモリを解放する ことを発見しました(両方の値には次の値が含まれます)。コマンド自体の実行に費やされた時間)。 時間間隔は、等条件下で使用して測定され、安定して再現されます。LinkInterrupt[link, 1]LinkClose[link]SessionTime[]

実際には、スレーブ カーネルのプロセスが既に強制終了され、そのメモリが既に解放されている場合にのみ戻るMathematicaの関数が必要です。と の両方が、スレーブ カーネルが終了するまで待機LinkInterrupt[link, 1]LinkClose[link]ません。現時点では、そのような機能はkillProc[procID]、このページの別の回答で示した機能だけのようです。

于 2011-03-10T02:13:54.900 に答える
1

現時点では、MathKernelプロセスを安全に強制終了する方法を 1 つしか知りません。この方法はNETLink、Windows でのみ機能するようであり、Microsoft .NET 2 以降をインストールする必要があります。

killProc[processID_] := If[$OperatingSystem === "Windows",
   Needs["NETLink`"];
   Symbol["LoadNETType"]["System.Diagnostics.Process"];
   With[{procID = processID},
    killProc[procID_] := (
       proc = Process`GetProcessById[procID];
       proc@Kill[]
       );
    ];
   killProc[processID]
   ];
(*Killing the current MathKernel process*)
killProc[$ProcessID]

任意の提案や改善をいただければ幸いです。

編集:

より正しい方法:

Needs["NETLink`"];
LoadNETType["System.Diagnostics.Process"];

$kern = LinkLaunch[First[$CommandLine] <> " -mathlink -noinit"];
LinkRead[$kern];
LinkWrite[$kern, Unevaluated[$ProcessID]];
$kernProcessID = First@LinkRead[$kern];
$kernProcess = Process`GetProcessById[$kernProcessID];

AbortProtect[If[! ($kernProcess@Refresh[]; $kernProcess@HasExited),
  $kernProcess@Kill[]; $kernProcess@WaitForExit[];
  $kernProcess@Close[]];
 LinkClose[$kern]]

編集2:

さらに正しい方法:

Needs["NETLink`"];
LoadNETType["System.Diagnostics.Process"];

$kern = LinkLaunch[First[$CommandLine] <> " -mathlink -noinit"];
LinkRead[$kern];
LinkWrite[$kern, Unevaluated[$ProcessID]];
$kernProcessID = First@LinkRead[$kern];
$kernProcess = Process`GetProcessById[$kernProcessID];

krnKill := AbortProtect[
   If[TrueQ[MemberQ[Links[], $kern]], LinkClose[$kern]];
   If[TrueQ[MemberQ[LoadedNETObjects[], $kernProcess]],
    If[! TrueQ[$kernProcess@WaitForExit[100]],
     Quiet@$kernProcess@Kill[]; $kernProcess@WaitForExit[]];
    $kernProcess@Close[]; ReleaseNETObject[$kernProcess];
    ]
   ];
于 2011-03-08T22:54:41.497 に答える