Intel MPI mpirun не завершает работу с помощью 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 мин опроса)?

1 ответ

Решение

Проблема в том, что реализация JDK destroy посылает SIGTERM, который выключается mpirun жесткий. Смотрите здесь для соответствующего источника JDK.

Вам необходимо отправить SIGINT чтобы дать MPI возможность корректно завершить работу.

Например Runtime.getRuntime().exec("kill -9 <pid>");

Вы можете получить PID, вызвав mpirun с --report-pid, (прочитайте справочную страницу)

редактировать

Вы также можете использовать отражение, чтобы выяснить PID процесса, который вы запустили под UNIX-подобной ОС (украдена отсюда). Поскольку мы говорим об убийстве и сигнале, это не должно быть ограничением.

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) {
  }
}
Другие вопросы по тегам