6

我需要执行 Reval多线程的方式执行 R s,这是Rserve非常好的。但是,如果一个实例的评估时间太长,我需要能够关闭正在计算阻塞评估的实例。据我测试,给定的实例将拒绝关闭,直到 eval 完成(显然,它需要在再次收听之前获取结果)。所以这是我的问题:

有没有办法在阻塞实例上获取 java 句柄(类似于Process对象)上获取 java 句柄,以便我可以蛮力杀死/终止 eval(类似于process.destroy())?换句话说,当我请求一个 eval(创建一个连接,抛出一个命令)时,我如何通过 java 建立正在处理的 eval 和与之相关的 Rsere 实例之间的关系?

还是我错过了一些关于 Rserve 已经允许处理这种需求的东西?

注意:我已经尝试通过serverEval()而不是在主实例上运行计算的常规运行所有东西(所有评估) eval,但这当然不令人满意,因为它只使用一个进程(主进程)。我可以杀死那个,但我的主要目标是能够单独关闭在单个实例上运行的阻塞评估。并且,自然地,保持我的 8 个 CPU 内核的优势,也就是说,保持并行性。否则使用 Rserve 是没有意义的(在这种情况下,JRI 引擎就绰绰有余了)。

注意:我想避免这种事情(线程),在不同的端口上处理主服务器本身的几个实例。这不是一个选择。

我已经尝试在 Rserve 的邮件列表中获取信息,但没有得到答复。我希望我让自己足够清楚,以便在这里得到答案或有用的评论。如果没有,请询​​问详情。非常感谢。

编辑:我还测试了 RCaller,它可以处理尽可能多的 R 实例,但是,因为它将结果写入 XML 文件以供以后从 java 端解析(不像 Rserve 那样真正使用通信协议),所以它太远了我必须执行的操作很慢...

4

2 回答 2

6

好的,这可以通过这种方式完成(从一些好心人那里得到,他最终在 Rserve 开发邮件列表上回答了我):

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

这允许跟踪与所述eval(R privides Sys.getpid())相关的实例的 pid。

然后停止/中止/取消,因为简单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 + "'.");

这样做的好处是独立于平台。

希望这能有所帮助。

于 2014-11-26T08:30:30.283 回答
1

怎么样

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

它将返回运行 Rserve(不是主)的 pid,然后您可以使用此 pid 杀死它。

于 2016-04-19T02:54:40.643 回答