12
votes

Mathkernel auto-redémarrant - est-il possible dans Mathematica?

Cette question provient de la question récente " Corriger à Cap Mathematica utilisation de la mémoire? "

Je me demande, est-il possible de redémarrer de manière programmée Mathkernel de garder le processus de frontage actuel connecté au nouveau processus de Mathkernel et d'évaluer certains code dans la nouvelle session de Mathkernel? Je veux dire un redémarrage "transparent" qui permet à un utilisateur de continuer à travailler avec le frontend lors de la création de nouveau processus de mathkernel frais avec un code du noyau précédent évalué / l'évaluation de celui-ci?

La motivation de la question est d'avoir un moyen d'automatiser le redémarrage de Mathkernel lorsqu'il faut trop de mémoire sans casser le calcul . En d'autres termes, le calcul doit être toujours poursuivi dans le processus de Mathkernel New Mathkernel sans interaction avec l'utilisateur (mais en gardant la possibilité d'interagir avec le mathematica comme il était à l'origine). Les détails sur quel code doivent être évalués dans le nouveau noyau sont bien sûr spécifiques pour chaque tâche de calcul. Je cherche une solution générale comment continuer automatiquement le calcul.


3 commentaires

Probablement une façon possible de résoudre le problème inclut le lancement de la programmation programmée de nouveau noyau à partir de la frontière, puis d'évaluer le code de ce nouveau noyau, puis de fermer l'ancien noyau de garder le nouveau noyau en cours d'exécution.


Que diriez-vous de conduire un noyau (appelez-le b) d'un autre (appelez-le a) et d'utiliser un superviseur? Bien sûr, cela nécessite une réorganisation du code. Mais vous avez sûrement pensé à cela et jeté l'approche?


@ACL Cette idée était la première (et le seul) que j'ai essayé. Et j'ai déjà mis en œuvre une telle fonctionnalité par Pure mathlink - mais mon chemin vraiment très difficile, extrêmement non élégant, s'appuie sur un grand nombre de fonctionnalités non documentées qui sont potentiellement spécifiques à une version. . Et le code est vraiment énorme! J'espère que le nouveau ScheduledTasks peut donner un moyen beaucoup plus élégant de résoudre ce problème.


6 Réponses :


2
votes

Vous pouvez terminer par programme le noyau à l'aide de sortie [] . Le front-end (ordinateur portable) démarrera automatiquement un nouveau noyau lorsque vous essayez ensuite d'évaluer une expression.

Préserver "Certains code du noyau précédent" va être plus difficile. Vous devez décider de ce que vous voulez conserver. Si vous pensez que vous voulez tout préserver, il ne sert à rien de redémarrer le noyau. Si vous savez quelles définitions que vous souhaitez enregistrer, vous pouvez utiliser Dumksave pour les écrire dans un fichier avant de terminer le noyau, puis utilisez <<< / code> pour charger ce fichier dans le fichier Nouveau noyau.

D'autre part, si vous savez quelles définitions prennent trop de mémoire, vous pouvez utiliser nonset , effacer , Clearall , ou supprimer pour supprimer ces définitions. Vous pouvez également définir une longueur d'historique de $ sur quelque chose de plus petit que Infinity (La valeur par défaut) Si c'est là que se passe votre mémoire.


2 commentaires

Le but est de poursuivre le calcul à partir d'un point sans interaction avec l'utilisateur.


@ALEXEYPOPKOV, je pense que Rob's Solution de Dumpsave et EXIT pourrait être implémenté de manière programmatique, mais la partie difficile sera la sélection automatique des définitions à enregistrer. Vous pouvez étendre définir pour ajouter une définition spécifiée à une liste qui sera enregistrée. Peut-être quelque chose de similaire à la technique utilisée dans MakecececeDreader .



0
votes

sonne comme un travail de nettoyage. xxx

de: http://library.wolfram.com/infocenter/technotes/4718/

"Nettoyantlate, essaie de faire tout ce qui est possible pour renvoyer le noyau à l'état dans lequel il s'agissait de l'élimination du nettoyage. m package a été initialement chargé. "


1 commentaires

CleanSlate est un utilitaire très simple et ancien. Il s'appuie sur supprimer et ne peut même pas protéger de Mémoire Fuites dues à la mise en cache interne . Évidemment CleanSlate n'est pas un moyen de gérer les fuites de mémoire. La seule approche fiable est de redémarrer le noyau.



5
votes

L'approche suivante exécute un noyau pour ouvrir un front-end avec son propre noyau, qui est ensuite fermé et rouvert, renouvelant le deuxième noyau.

Ce fichier est l'entrée Mathkernel, c: \ temp \ test4.m xxx

Le cahier de démonstration, c: \ temp \ run.nb contient deux cellules: xxx

Le noyau initial s'ouvre Un front-end et exécute la première cellule, puis il quitte le front-end, le répète et exécute la deuxième cellule.

Le tout peut être exécuté soit en collant (en une seule fois) l'entrée Mathkernel dans une session de noyau, soit à partir d'un fichier de lot, par exemple. C: \ temp \ runtest2.bat xxx

C'est un peu élaboré à configurer, et dans sa forme actuelle, cela dépend de savoir combien de temps attendre avant de fermer et de redémarrer la seconde noyau.


1 commentaires

+1 génial! Mais j'estime qu'il devrait y avoir une solution plus simple à travers des jetons de frontends non bien documentés, disponibles dans le menu "Évaluation" de Frontend: "Démarrer le noyau" (permet de démarrer un nouveau noyau qui est déjà configuré dans la boîte de dialogue "Options de configuration du noyau". ), "Noyau par défaut" (permet de définir un autre noyau par défaut pour le cahier actuel). Le problème réel est de savoir comment configurer un nouveau noyau à l'aide de la boîte de dialogue "Options de configuration du noyau" par programme et comment évaluer dans le nouveau noyau du code du noyau d'origine.



5
votes

Peut-être que les machines de calcul parallèles pourraient être utilisées pour cela? Voici une configuration brute qui illustre l'idée:

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
  ]


0 commentaires

9
votes

à partir d'un Commentaire de Arnoud Buzing hier, sur Stack Exchange Mathematica Chat, citant entièrement:

Dans un ordinateur portable, si vous avez plusieurs cellules, vous pouvez mettre cesser de fumer dans une cellule en soi et définir cette option: xxx

alors si vous avez une cellule au-dessus de lui et en dessous et sélectionnez les trois et évaluez tous les trois, le noyau cessera de fumer, mais la file d'attente de l'évaluation frontale continuera (et redémarrera le noyau pour la dernière cellule).

- Arnoud Buzing


0 commentaires

3
votes

J'ai une exigence similaire lorsque je gère une cudacée pour une longue boucle et Cudalink a manqué de mémoire (semblable ici: https://mathematica.stackexchange.com/questions/31412/cudalink-ran-out-of-available-Memory ). Il n'y a aucune amélioration sur la fuite de mémoire même avec la dernière version Mathematica 10.4. Je trouve une solution de contournement ici et j'espère que vous pourriez trouver que c'est utile. L'idée est que vous utilisez un script Bash pour appeler un programme Mathematica (exécuté en mode batch) plusieurs fois avec les paramètres de passage du script Bash. Voici l'instruction de détail et la démo (ceci est pour la fenêtre OS):


1 commentaires

Cette solution de contournement a un avantage sur le chemin de Chris Degnen, c'est que vous n'avez pas à gérer le temps d'attente.