Как завершить с сигналом с MPI - PullRequest
0 голосов
/ 27 апреля 2018

Это моя первая программа, которую я написал с использованием MPI на языке c. Предполагается, что программа должна завершиться в течение 15 секунд, но этого не произошло. он даже не прошел оператор if (end_now == 1). Кто-нибудь знает, что здесь произошло? Код упрощен, как показано ниже:

int end_now = 0;


void sig_handler(int signo)
{
    if (signo == SIGUSR1) {
        end_now = 1;
        printf ( "  %8d  %8d\n", current_number, current_total);
    }
}

int main ( int argc, char **argv ){
   int id;
   int count;

   MPI_Init (&argc, &argv);
   MPI_Comm_size (MPI_COMM_WORLD, &count);
   MPI_Comm_rank (MPI_COMM_WORLD, &id);

   signal(SIGUSR1, sig_handler);


   while (1){
       //MPI_Allreduce is called here to sum up the subtotal calculated by child processes
        if (end_now == 1){
            printf("here\n");  //this "here is never printed out"
            break;
        }
    }
    MPI_Finalize ();
    return 0;
}

Я использую тайм-аут --signal = USR1 15 mpirun.openmpi -np 2 ./a.out для выполнения кода на моем Mac. Спасибо всем, кто может помочь.

Ответы [ 4 ]

0 голосов
/ 10 августа 2018

Я рекомендую не использовать printf в обработчиках сигналов, так как printf не является функцией reentable, и это может привести к сбою программы на некоторых платформах.

0 голосов
/ 27 апреля 2018

end_now также должен быть объявлен как volatile, иначе компилятор может оптимизировать основной цикл, который будет работать вечно.

0 голосов
/ 27 апреля 2018

Снефтель прав. Жиль Гуаиллардет тоже ОЧЕНЬ прав. Я хочу добавить другую информацию.

Даже если вы отправляете сигнал в реальную программу, а не в «mpirun», вы, возможно, отправляете его ОДНОМУ только из ваших процессов, а не всем.

Да, сигналы не являются правильной вещью в программах MPI. Но даже если вы хотите их использовать, вы должны сначала отладить все процессы, которые их получают, и кто из них их получает.

Вставьте «printf» непосредственно в обработчик сигнала. Напечатайте что-то вроде «Процесс MPI с номером% d получил сигнал» и вставьте MPI_COMM_RANK в этот printf. (UPD 2018-04-27 7:31 MSK: извините, я не заметил, что у вас уже есть такой printf в Ваш код.) (Примечание: я думаю, что "printf" в программах MPI допускается только в первом процессе, и использование "printf" в других процессах, вероятно, плохая идея, но для целей отладки пойдет. Также я думаю, что "printf" напрямую из Обработчик сигналов - плохая идея, но, опять же, для целей отладки.)

Вы определите, получают ли ваши процессы сигнал и какой из них.

Если вы не удовлетворены результатами, попробуйте другие программы вместо gtimeout. Например, «тайм-аут» из GNU Coreutils. (Ну, это Mac, я не уверен, GNU Coreutils доступен с Mac, но я все еще думаю, что вы можете найти НЕКОТОРЫЕ «тайм-ауты».)

Тогда: вы не описали свою установку в вопросе. Ваши MPI-программы работают на разных хостах или на одном? Реализуются ли MPI-программы как отдельные программы или как потоки? Какую реализацию MPI вы используете и какую версию? Если вы не знаете, как MPI запускает ваши процессы, по крайней мере, сообщите нам, как вы установили реализацию MPI и как вы ее настроили.

Или даже вы можете обойтись без "timeout" или "gtimeout" вообще. Просто введите это в одной консоли:

sh -c 'echo $$ > ~/pid-of-mpirun; exec ~/opt/usr/local/bin/mpirun -np 2 ./a.out'

Это запустит "mpirun" при сохранении его PID в ~ / pid-of-mpirun. И запустить параллельно в другом терминале (конечно, вам не нужно запускать эту команду в один и тот же момент):

sleep 15; kill -USR1 $(cat ~/pid-of-mpirun)

Это потребует 15 секунд и отправит USR1 для обработки того, какой PID находится в ~ / pid-of-mpirun.

Но все это, вероятно, отправит USR1 в "mpirun", а не в реальные процессы (я не уверен, проверьте это!). Как отправить на актуальные процессы? Что ж, вы можете прочитать страницу руководства по "kill" и попытаться понять, как отправить сигнал всей группе процессов, а не только одному процессу.

Кроме того, вы можете записать свой PID в какой-то файл непосредственно внутри вашей программы на C.

Пример:

#include <stdio.h>
#include <unistd.h> // Mac is one of UNIX systems, so we have unistd.h
// ...
FILE *fout = fopen("~/my-pid", "w"); fprintf(fout, "%d\n", getpid); fclose(fout);

Конечно, вы должны каким-то образом убедиться, что вы создаете разные файлы в разных процессах. Например, сгенерируйте имена файлов из MPI_COMM_RANK.

0 голосов
/ 27 апреля 2018

Вы отправляете сигнал на mpirun, а не на свой исполняемый файл. Поскольку mpirun сам по себе не имеет обработчика SIGUSR1, ничего не происходит.

Кстати, использование сигналов с программами MPI - это не то, что вы хотите делать. Программы MPI полагаются на множественные вызовы, выполняющиеся в режиме блокировки, что не соответствует асинхронному характеру сигналов для каждого процесса.

...