簡體   English   中英

如何使用MPI終止Signal

[英]How to terminate with Signal with MPI

這是我用C在MPI中編寫的第一個程序,該程序應該在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上執行代碼。 感謝任何人的幫助。

您正在向mpirun發送信號,而不是向可執行文件發送信號。 由於mpirun本身沒有SIGUSR1處理程序,因此不會發生任何事情。

順便說一句,將信號與MPI程序一起使用並不是您要做的事情。 MPI程序依賴於以鎖步方式運行的多個調用,這與信號的異步和按進程性質不匹配。

Sneftel是正確的。 Gilles Gouaillardet也非常正確。 我想添加一些其他信息。

即使您將信號發送到實際程序而不是“ mpirun”,那么也可能僅將信號發送給您的所有進程之一,而不是所有進程。

是的,在MPI程序中信號不正確。 但是,即使您想使用它們,也應該首先調試獲取它們的過程以及由誰獲取的過程。

將“ printf”直接插入信號處理程序。 打印類似“ MPI進程號%d收到信號”之類的內容,然后將MPI_COMM_RANK插入此printf中。 (UPD 2018-04-27 7:31 MSK:抱歉,我沒有注意到您的代碼中已經有這樣的printf 。)(注意:我認為MPI程序中的“ printf”僅在第一個過程中允許,並且使用“ printf” “在其他進程中可能不是個好主意,但出於調試目的而已。此外,我認為直接從信號處理程序中獲取“ printf”是一個壞主意,但出於調試目的也將成為現實。)

您將確定您的進程是否能收到信號,以及哪個信號。

如果您對結果不滿意,請嘗試使用其他程序代替gtimeout。 例如,GNU Coreutils中的“超時”。 (嗯,這是Mac,我不確定GNU Coreutils是否可以從Mac使用,但我仍然認為您可以找到某些“超時”。)

然后:您沒有描述您的設置。 您的MPI程序是在不同的主機上運行還是在一個主機上運行? MPI“程序”是否真的以單獨的程序或線程的形式實現? 您使用哪個MPI實現和哪個版本? 如果您不知道MPI如何啟動您的流程,至少可以告訴我們,如何安裝MPI實施以及如何配置它。

甚至可以完全不使用任何“超時”或“ gtimeout”。 只需在一個控制台中輸入以下內容即可:

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

這將在將其PID存儲到〜/ pid-of-mpirun的同時運行“ mpirun”。 並在另一個終端中並行運行(當然,您不需要完全在同一時間運行此命令):

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

這將需要15秒,然后發送USR1來處理〜/ pid-of-mpirun中的PID。

但是所有這一切可能會將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生成文件名。

還應將end_now聲明為volatile否則編譯器可能會優化將永遠運行的主循環。

我建議不要在信號處理程序中使用printf,因為printf是不可重入的函數,在某些平台上這可能導致程序崩潰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM