2014-11-21 3 views
6

Мне нужно выполнить R eval с многопоточным способом, что-то вроде Rserve. Но, если оценка одного экземпляра занимает слишком много времени, мне нужно иметь возможность закрыть экземпляр, который вычисляет блокировку eval. Насколько я тестировал, данный экземпляр откажется от выключения до тех пор, пока не будет выполнено eval (видимо, ему нужно получить результат, прежде чем снова слушать). Итак, вот мой вопрос:Rserve server: как прервать блокирующий экземпляр (eval принимает навсегда)?

Есть ли способ получить java-дескриптор блокирующего экземпляра (что-то вроде объекта Process), чтобы я мог принудительно убить/закончить eval (что-то вроде process.destroy())? Другими словами, когда я запрашиваю eval (создаю соединение, бросаю команду), как установить связь между обработанным eval и экземпляром Rsere, связанным с ним, через java?

Или я пропустил что-то о Rserve, которое уже позволяет справляться с такими потребностями?

Примечание: я уже пытался запустить все (все Evals) через serverEval() вместо обычной eval, которая проходит вычисления на основном, например, но это, конечно, не удовлетворяет, как он использует только один процесс (основной). Тот, который я могу убить, но моя главная цель состояла в том, чтобы иметь возможность индивидуально блокировать блокировку eval, работающую на отдельном экземпляре. И, естественно, сохраняйте преимущество моих 8 ядер процессора, то есть сохраняйте параллелизм. Нет смысла использовать Rserve иначе (JRI-движок был бы более чем достаточным в этом случае).

Примечание: Я бы хотел избежать таких вещей (thread), имея дело с несколькими экземплярами самого главного сервера на разных портах. Это не вариант.

Я уже пытался получить информацию о списке рассылки Rserve, но на него не ответил. Надеюсь, я сделал себе достаточно ясно, чтобы получить ответ или полезный комментарий здесь. Если нет, просьба уточнить подробности. Большое спасибо заранее.

Edit: Я также протестировал RCaller, которая занимается так много случаев R одной необходимости, но, как пишут результаты в файлы XML для последующего разбора из стороны Java (на самом деле не используя протокол связи, как Rserve бы), это слишком медленно для того, что я должен выполнить ...

ответ

6

ОК, это может быть сделано таким образом (поймал его с какой-то хороший человек, который наконец-то ответил мне на Rserve список рассылки Devel):

В потоке, выполняющем eval, предполагается, что он блокируется или слишком длинный, и при запуске Rserve запускается:

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..."); 

Это позволяет отслеживать pid экземпляра, связанного с указанным eval (R prideses Sys.getpid()).

Затем остановить/прервать/отменить и так как простой this.rEngine.close() не остановит обработку задачи на стороне сервера, но только закрывает соединение, нам нужно убить целевой экземпляр Rserve. Это можно сделать, вызвав tools::pskill() (или любой другой системный вызов, например, возможно, kill -9 my_pid (UNIX *), TASKKILL /PID my_pid /F (Windows), ..., В зависимости от платформы), очевидно, из другого потока, чем выше один (который ждет «Eval части», чтобы вернуться):

// 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 + "'."); 

Это один имеет преимущество, чтобы быть независимым с копирайтом.

Надеюсь, это поможет.

+0

Это работает. Но если я попробую что-то вроде rEngine = new RConnection(); // Получаем pid rEngine и выполняем долгое время eval с помощью rEngine. // Завершение RConnection c2 = new RConnection(); // SIGTERM не может быть понят везде: так, используя сигнал SIGKILL. c2.eval ("tools :: pskill (" + this.rServePid + ")"); c2.eval («tools :: pskill (« + this.rServePid + », tools :: SIGKILL)»); c2.close(); ', процесс убит, но использование Rserve в процессоре растет, а Rserver не разрешает никаких новых подключений. Вы знаете, почему? – raiyan

+0

Похоже, что последний 'eval' не возвращается и продолжает занимать целую ядро. В некоторых случаях вам нужно будет получить все дерево процессов (необходимо убить родительский процесс, чтобы действительно отключить эту вещь). Конечно, этот подход зависит от платформы. У меня есть сценарии для Windows/OSX и NUX для этого вместо (система называется). Дайте мне знать, если вам нужен более конкретный материал. Приветствия. –

+0

Я не хочу убивать все дерево процессов. Кто-то другой будет работать над одним и тем же Rserve, и убийство всего процесса также убьет их экземпляр. Однако проблема заключается не в eval. Eval возвращается, и выполнение кода переходит к следующей строке. Но использование процессора пики при убийстве экземпляра. – raiyan

0

Как насчет

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

Она возвращает идентификатор процесса бега Rserve (не основной), а затем вы можете убить его, используя этот идентификатор процесса.

 Смежные вопросы

  • Нет связанных вопросов^_^