英特尔 MPI mpirun 不会使用 java Process.destroy() 终止

Intel MPI mpirun does not terminate using java Process.destroy()

我的 Intel MPI 版本是 impi/5.0.2.044/intel64 安装在 RHEL 机器上。

我正在使用 java 通过以下代码调用 MPI 程序:

ProcessBuilder builder = new ProcessBuilder();
builder.command("mpirun ./myProgram");
builder.redirectError(Redirect.to(new File("stderr")));
builder.redirectOutput(Redirect.to(new File("stdout")));
Process p = null;
try {
    p = builder.start();
} catch (IOException e) {
    e.printStackTrace();
}
// Process has started here
p.destroy();
try {
    // i = 143
    int i = p.exitValue();
} catch( IllegalThreadStateException e){
}

但是即使知道exitValue()没有抛出异常,ps aux仍然显示一堆./myProgram,并且程序仍在写入结果文件,就好像它没有被被杀死,仅在完成所有计算后终止。

目前,我发现成功终止 ./myProgram 的唯一方法是在 java 程序的控制台中使用 Ctrl+C 终止 java。

我的意图是立即停止计算,让 java 程序安排一些其他计算。是否有任何变通办法强制所有 mpi 实例终止,或者至少保证在短的、确定的时间内终止(例如 30 秒或 1 分钟的轮询)?

问题是 destroy 的 JDK 实现发送了 SIGTERM,它很难关闭 mpirun。 有关 JDK 来源,请参阅 here

您需要发送 SIGINT 让 MPI 有机会正常关闭。

例如Runtime.getRuntime().exec("kill -9 <pid>");

您可以通过调用 mpirun--report-pid 来获取 PID。 (阅读手册页)

编辑

您也可以使用反射来计算您在类 UNIX OS 下启动的进程的 PID(从 here 中窃取)。当我们谈论 kill 和 signal 时,这不应该是一个限制。

if(process.getClass().getName().equals("java.lang.UNIXProcess")) {
  /* get the PID on unix/linux systems */
  try {
    Field f = process.getClass().getDeclaredField("pid");
    f.setAccessible(true);
    pid = f.getInt(p);
  } catch (Throwable e) {
  }
}