cout最慢的处理器MPI

时间:2015-09-17 14:25:15

标签: c++ c++11 mpi cout

我正在使用MPI编写程序。每个处理器执行for循环:

int main(int argc, char** argv) {
  boost::mpi::environment env(argc, argv);

  for( int i=0; i<10; ++i ) {
    std::cout << "Index " << i << std::endl << std::flush;
  }
}

有没有办法让cout只发生在最后一个处理器上才能命中i?或标记所以只在最后一个处理器上执行一行才能到达它?

1 个答案:

答案 0 :(得分:6)

它可能看起来很简单,但实际上,你在这里要求的内容对于像MPI这样的分布式内存模型来说非常复杂......

在共享内存环境中,例如OpenMP,通过定义共享计数器,通过所有线程原子递增,然后检查它是否与线程数相对应,可以轻松解决这个问题。 。如果是这样,那么这意味着所有线程都通过了点,当前是最后一个,他将负责打印。

在分布式环境中,定义和更新此类共享变量非常复杂,因为每个进程都可能在远程计算机上运行。为了保持这一点,MPI建议自MPI-2.0内存窗口和单向通信。然而,即便如此,也不可能正确地实现原子计数器增量,同时还能可靠地获得它的值。只有MPI 3.0和MPI_Fetch_and_op()函数的引入才有可能。以下是实施示例:

#include <mpi.h>
#include <iostream>

int main( int argc, char *argv[] ) {

    // initialisation and inquiring of rank and size
    MPI_Init( &argc, &argv);

    int rank, size;
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
    MPI_Comm_size( MPI_COMM_WORLD, &size );

    // creation of the "shared" counter on process of rank 0
    int *addr = 0, winSz = 0;
    if ( rank == 0 ) {
        winSz = sizeof( int );
        MPI_Alloc_mem( winSz, MPI_INFO_NULL, &addr );
        *addr = 1; // initialised to 1 since MPI_Fetch_and_op returns value *before* increment
    }
    MPI_Win win;
    MPI_Win_create( addr, winSz, sizeof( int ), MPI_INFO_NULL, MPI_COMM_WORLD, &win );

    // atomic incrementation of the counter
    int counter, one = 1;
    MPI_Win_lock( MPI_LOCK_EXCLUSIVE, 0, 0, win );
    MPI_Fetch_and_op( &one, &counter, MPI_INT, 0, 0, MPI_SUM, win );
    MPI_Win_unlock( 0, win );

    // checking the value of the counter and printing by last in time process
    if ( counter == size ) {
        std::cout << "Process #" << rank << " did the last update" << std::endl;
    }

    // cleaning up
    MPI_Win_free( &win );
    if ( rank == 0 ) {
        MPI_Free_mem( addr );
    }
    MPI_Finalize();

    return 0;
}

正如您所看到的,对于这样一个微不足道的请求,这是非常冗长和复杂的。而且,这需要MPI 3.0支持。

不幸的是,Boost.MPI似乎是你的目标,只有&#34;支持MPI 1.1&#34;中的大多数功能。因此,如果您真的想要获得此功能,则必须使用一些简单的MPI编程。