Как безопасно убить подчиненное ядро?
LinkClose[link]
"не обязательно завершать программу на другом конце соединения", как сказано в Документации. Есть ли способ безопасно убить процесс подчиненного ядра?
РЕДАКТИРОВАТЬ:
На самом деле мне нужна функция в Mathematica, которая возвращает только тогда, когда процесс подчиненного ядра уже уничтожен и его память уже освобождена. И то и другое LinkInterrupt[link, 1]
а также LinkClose[link]
не ждите, пока ведомое ядро выйдет. В данный момент, похоже, единственной такой функцией является killProc[procID]
Функция, которую я показал в одном из ответов на этой странице. А есть встроенный аналог?
2 ответа
На данный момент я знаю только один способ убить MathKernel
процесс безопасно. Этот метод использует 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];
]
];
Тодд Гэйли ответил на мой вопрос в группе новостей. Решение состоит в том, чтобы отправить подчиненному ядру MLTerminateMessage
, Из кода верхнего уровня:
LinkInterrupt[link, 1] (* An undocumented form that lets you pick
the message type *)
В С:
MLPutMessage(link, MLTerminateMessage);
В Java с использованием J/Link:
link.terminateKernel();
В.NET с помощью.NET/Link:
link.TerminateKernel();
РЕДАКТИРОВАТЬ:
Я обнаружил, что в стандартных случаях при использовании LinkInterrupt[link, 1]
моя операционная система (Windows 2000 на данный момент) освобождает физическую память только за 0,05-0,1 секунды, начиная с момента выполненияLinkInterrupt[link, 1]
в то время как с LinkClose[link]
он освобождает физическую память за 0,01-0,03 секунды (оба значения включают время, затраченное на выполнение самой команды). Временные интервалы измерялись с помощью SessionTime[]
в равных условиях и постоянно воспроизводятся.
На самом деле мне нужна функция в Mathematica, которая возвращается только тогда, когда процесс подчиненного ядра уже завершен и его память уже освобождена. И то и другое LinkInterrupt[link, 1]
а также LinkClose[link]
не ждите, пока ведомое ядро выйдет. В данный момент, похоже, единственной такой функцией является killProc[procID]
Функция, которую я показал в другом ответе на этой странице.