2011-03-03 21 views
7

我具有使用該實施的openmpi的MPI_Barrier一些同步問題的openmpi MPI_Barrier問題

int rank; 
int nprocs; 

int rc = MPI_Init(&argc, &argv); 

if(rc != MPI_SUCCESS) { 
    fprintf(stderr, "Unable to set up MPI"); 
    MPI_Abort(MPI_COMM_WORLD, rc); 
} 

MPI_Comm_size(MPI_COMM_WORLD, &nprocs); 
MPI_Comm_rank(MPI_COMM_WORLD, &rank); 


printf("P%d\n", rank); 
fflush(stdout); 

MPI_Barrier(MPI_COMM_WORLD); 

printf("P%d again\n", rank); 

MPI_Finalize(); 

爲的mpirun -n 2 ./a.out

輸出應爲: P0 P1 .. 。

輸出是有時: P0 P0再次 P1 P1再次

發生了什麼事?

回答

13

您的終端上顯示的打印輸出行的順序不一定是打印事件的順序。您正在使用共享資源(stdout),因此總是有訂購問題。 (並且fflush在這裏沒有幫助,stdout是無論如何都是行緩存的。)

您可以嘗試在輸出前添加一個時間戳,並將所有這些保存到不同的文件中,每個MPI進程一個。

然後檢查您的日誌,您可以將兩個文件合併在一起,並根據時間戳進行排序。

那麼你的問題應該消失。

+1

如果MPI進程在不同的節點上運行,則依賴時間戳可能並不理想,除非您可以保證時鐘已同步。 – 2011-03-03 17:05:00

+1

@Shawn:有MPI_Wtime()。 – suszterpatt 2011-03-03 18:15:51

+3

@suszterpatt:'MPI_Wtime()'通常不是全局/同步時鐘! (只有在'MPI_WTIME_IS_GLOBAL'被定義併爲true時) – Zulan 2011-03-03 18:30:59

10

MPI_Barrier()沒有錯。

由於Jens mentioned,你沒有看到你所期望的輸出的原因是因爲標準輸出緩衝在每個進程。不能保證來自多個進程的打印將依次顯示在調用進程中。 (如果將每個進程的stdout實時傳輸到主進程進行打印,將會導致大量不必要的通信!)

如果您想讓自己確信屏障正常工作,您可以嘗試寫入文件來代替。將多個進程寫入單個文件可能會導致額外的複雜性,因此您可以讓每個進程寫入一個文件,然後在關閉之後交換寫入的文件。例如:

Proc-0   Proc-1 
     |     | 
f0.write(..)  f1.write(...) 
     |     | 
     x ~~ barrier ~~ x 
     |     | 
f1.write(..)  f0.write(...) 
     |     | 
    END    END 

樣品實施:

#include "mpi.h" 
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) { 
    char filename[20]; 
    int rank, size; 
    FILE *fp; 

    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 

    if (rank < 2) { /* proc 0 and 1 only */ 
     sprintf(filename, "file_%d.out", rank); 
     fp = fopen(filename, "w"); 
     fprintf(fp, "P%d: before Barrier\n", rank); 
     fclose(fp); 
    } 

    MPI_Barrier(MPI_COMM_WORLD); 

    if (rank < 2) { /* proc 0 and 1 only */ 
     sprintf(filename, "file_%d.out", (rank==0)?1:0); 
     fp = fopen(filename, "a"); 
     fprintf(fp, "P%d: after Barrier\n", rank); 
     fclose(fp); 
    } 

    MPI_Finalize(); 
    return 0; 

} 

運行代碼後,你應該得到以下結果:

[[email protected]]$ cat file_0.out 
P0: before Barrier 
P1: after Barrier 

[[email protected]]$ cat file_1.out 
P1: before Barrier 
P0: after Barrier 

的所有文件,在 「後障」 中的語句總是晚點出現。

+0

優秀的解釋... :) – RoboAlex 2012-05-25 06:51:18

3

在MPI程序中不保證輸出順序。

這與MPI_Brier完全無關。

此外,我不會花太多時間來擔心MPI程序的輸出順序。

如果你真的想要的話,最優雅的方法是讓進程將他們的消息發送到一個等級,比如等級爲0,並讓等級0按照接收到的順序打印輸出或排序按等級排列。

再一次,不要花太多時間嘗試從MPI程序訂購輸出。這是不實際的,沒有多大用處。