2014-11-21 7 views
6

Ich muss R eval s in einer Multi-Threading-Art durchführen, die etwas Rserve bietet ziemlich gut. Aber wenn das Evaluieren einer Instanz zu lange dauert, muss ich die Instanz herunterfahren können, die das Blocking Eval berechnet. Soweit ich es getestet habe, wird die angegebene Instanz das Herunterfahren verweigern, bis das Eval abgeschlossen ist (anscheinend muss es das Ergebnis holen, bevor es wieder zu hören ist). Also hier ist meine Frage:Rserve-Server: Wie wird eine blockierende Instanz beendet (eval dauert ewig)?

Gibt es eine Möglichkeit, ein Java-Handle auf der blockierenden Instanz (so etwas wie ein Process Objekt), so dass ich Brute Force töten/terminieren die Eval (etwas wie process.destroy())? Mit anderen Worten, wenn ich nach einem eval (erstellen Sie eine Verbindung, werfen Sie einen Befehl) fragen, wie stelle ich eine Beziehung zwischen dem eval in Bearbeitung, und die Instanz von Rsere im Zusammenhang mit ihm, über Java?

Oder habe ich etwas über Rserve vermisst, was bereits erlaubt, mit dieser Art von Bedürfnissen umzugehen?

Hinweis: ich schon alles versucht (alle evals) über serverEval() statt der regulären eval zu laufen, die die Berechnungen auf der Hauptinstanz läuft, aber das ist natürlich nicht befriedigend, wie es verwendet nur einen Prozess (der Haupt). Diesen kann ich töten, aber mein Hauptziel war es, ein Blocking-Eval einzeln herunterfahren zu können, das auf einer einzelnen Instanz läuft. Und natürlich, behalten Sie den Vorteil meiner 8 CPU-Kerne, das heißt, bewahren Sie die Parallelität. Es hat keinen Sinn, Rserve anderweitig zu verwenden (JRI-Engine wäre in diesem Fall mehr als ausreichend).

Hinweis: Ich möchte diese Art von Dingen vermeiden (thread), mit mehreren Instanzen des Hauptservers selbst, auf verschiedenen Ports. Das ist keine Option.

Ich habe schon versucht, Informationen über Rserves Mailingliste zu bekommen, aber wurde nicht beantwortet. Ich hoffe, ich habe mich klar genug gemacht, um hier eine Antwort oder einen hilfreichen Kommentar zu erhalten. Wenn nicht, bitte fragen Sie nach Details. Vielen Dank im voraus.

Edit: ich auch RCaller getestet, die mit so vielen Fällen von R eine Notwendigkeit befasst, aber, wie es später Ergebnisse in XML-Dateien zu schreiben, um von Java-Seite Parsen (nicht wirklich ein Kommunikationsprotokoll als rserve Verwendung würde), ist es viel zu langsam für das, was ich durchführen müssen ...

Antwort

6

OK, kann dies auf diese Weise durchgeführt werden (es von einigen netten Person gefangen, die auf rserve devel Mailing-Liste beantwortet mir endlich):

In dem Thread, der die eval blockiert oder zu lange ausgeführt wird, und unter der Annahme, dass Rserve gestartet wird:

private RConnection rEngine = null; 
private int rServePid = -1; 

//... 

// Keep an opened instance and store the related pid 
RConnection rconn = new RConnection(); 
this.rServePid = rconn.eval("Sys.getpid()").asInteger(); 
this.rEngine = rconn; 
LOG.info("Rserve: started instance with pid '" + this.rServePid + "'."); 
//... 
this.rEngine.eval("some consuming code..."); 

Dies ermöglicht es, die PID der Instanz im Zusammenhang mit der genannten eval (R privides Sys.getpid()) zu verfolgen.

Dann zu stoppen/abbrechen/abbrechen und da eine einfache this.rEngine.close() nicht die Aufgabe auf der Serverseite zu stoppen, sondern nur die Verbindung zu beenden, müssen wir die gezielte Rserve-Instanz zu töten. Dies kann durch den Aufruf von tools::pskill() (oder einem anderen Systemanruf wie möglicherweise kill -9 my_pid10 (UNIX *), TASKKILL /PID my_pid /F (Windows), ... erfolgen., Auf der Plattform je), offensichtlich von einem anderen Thread als die oben (die für den „eval Teil“ warten zurückzukehren):

// Terminate. 
RConnection c2 = new RConnection(); 
// SIGTERM might not be understood everywhere: so using SIGKILL signal, as well. 
c2.eval("tools::pskill("+ this.rServePid + ")"); 
c2.eval("tools::pskill("+ this.rServePid + ", tools::SIGKILL)"); 
c2.close(); 
LOG.info("Rserve: terminated instance with pid '" + this.rServePid + "'."); 

, dass man den Vorteil, unabhängig zu sein hat Plateform.

Hoffe, das kann helfen.

+0

Das funktioniert. Aber wenn ich etwas wie "rEngine = new RConnection(); // Holen Sie sich die pid von rEngine und die zeitaufwendige Eval mit rEngine .. // Beenden RConnection c2 = neue RConnection(); // SIGTERM ist vielleicht nicht überall zu verstehen: also auch das SIGKILL-Signal. c2.eval ("tools :: pskill (" + this.rServePid + ")"); c2.eval ("tools :: pskill (" + this.rServePid + ", Werkzeuge :: SIGKILL)"); c2.close(); ', Der Prozess wird beendet, aber die CPU-Nutzung von Rserve steigt und Rserver lässt keine neuen Verbindungen zu. Hast du eine Ahnung warum? – raiyan

+0

Klingt wie das letzte 'eval' nicht zurückkehrt und weiterhin einen ganzen Kern besetzt. In einigen Fällen müssen Sie den gesamten Prozessbaum abrufen (Sie müssen den übergeordneten Prozess beenden, um das Objekt wirklich auszuschalten). Natürlich ist dieser Ansatz plattformabhängig. Ich habe dafür stattdessen Windows/OSX und NUX Batch-Skripte (System genannt). Lassen Sie es mich wissen, wenn Sie mehr spezifisches Material benötigen. Prost. –

+0

Ich möchte nicht den gesamten Prozessbaum töten. Jemand anderes wird an demselben Rserve arbeiten und das Töten des gesamten Prozesses wird auch ihre Instanz töten. Das Problem ist nicht mit der Eval obwohl. Eval kehrt zurück und die Codeausführung geht weiter zur nächsten Zeile. Die CPU-Nutzung erreicht jedoch den höchsten Wert beim Töten einer Instanz. – raiyan

0

Wie wäre es

rcon.eval("system(\"echo $$\", intern = TRUE)"); 

Es wird wieder pid der laufenden rserve (nicht der Haupt) und dann kann man es töten, indem sie diese pid verwenden.