簡體   English   中英

為什么mpi_bcast比mpi_reduce慢得多?

[英]why is mpi_bcast so much slower than mpi_reduce?

使用MPI,我們可以進行廣播以將陣列發送到多個節點,也可以簡化將多個節點上的陣列組合到一個節點上。

我猜想,實現這些目標的最快方法將是使用二叉樹,其中每個節點要么發送到兩個節點(bcast),要么減少兩個節點(reduce),這將使節點數量成為時間的對數。

似乎沒有任何理由會比減少廣播特別慢?

我在4台計算機的群集上運行了以下測試程序,其中每台計算機具有12個內核。 奇怪的是,廣播比減少慢很多。 為什么? 有什么我可以做的嗎?

結果是:

inited mpi: 0.472943 seconds
N: 200000 1.52588MB
P = 48
did alloc: 0.000147641 seconds
bcast: 0.349956 seconds
reduce: 0.0478526 seconds
bcast: 0.369131 seconds
reduce: 0.0472673 seconds
bcast: 0.516606 seconds
reduce: 0.0448555 seconds

代碼是:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <sys/time.h>
using namespace std;

#include <mpi.h>

class NanoTimer {
public:
   struct timespec start;

   NanoTimer() {
      clock_gettime(CLOCK_MONOTONIC,  &start);

   }
   double elapsedSeconds() {
      struct timespec now;
      clock_gettime(CLOCK_MONOTONIC,  &now);
      double time = (now.tv_sec - start.tv_sec) + (double) (now.tv_nsec - start.tv_nsec) * 1e-9;
      start = now;
      return time;
   }
    void toc(string label) {
        double elapsed = elapsedSeconds();
        cout << label << ": " << elapsed << " seconds" << endl;        
    }
};

int main( int argc, char *argv[] ) {
    if( argc < 2 ) {
        cout << "Usage: " << argv[0] << " [N]" << endl;
        return -1;
    }
    int N = atoi( argv[1] );

    NanoTimer timer;

    MPI_Init( &argc, &argv );
    int p, P;
    MPI_Comm_rank( MPI_COMM_WORLD, &p );
    MPI_Comm_size( MPI_COMM_WORLD, &P );
    MPI_Barrier(MPI_COMM_WORLD);
    if( p == 0 ) timer.toc("inited mpi");
    if( p == 0 ) {
        cout << "N: " << N << " " << (N*sizeof(double)/1024.0/1024) << "MB" << endl;
        cout << "P = " << P << endl;
    }
    double *src = new double[N];
    double *dst = new double[N];
    MPI_Barrier(MPI_COMM_WORLD);
    if( p == 0 ) timer.toc("did alloc");

    for( int it = 0; it < 3; it++ ) {    
        MPI_Bcast( src, N, MPI_DOUBLE, 0, MPI_COMM_WORLD );    
        MPI_Barrier(MPI_COMM_WORLD);
        if( p == 0 ) timer.toc("bcast");

        MPI_Reduce( src, dst, N, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD );
        MPI_Barrier(MPI_COMM_WORLD);
        if( p == 0 ) timer.toc("reduce");
    }

    delete[] src;

    MPI_Finalize();
    return 0;
}

群集節點正在運行64位ubuntu 12.04。 我同時嘗試了openmpi和mpich2,並獲得了非常相似的結果。 該網絡不是千兆以太網,它不是最快的,但我最好奇的不是絕對速度,而是廣播和縮減之間的差距。

我認為這不能完全回答您的問題,但希望它能提供一些見識。

MPI只是一個標准。 它沒有定義每個函數的實現方式。 因此,MPI中某些任務的性能(在您的情況下為MPI_Bcast和MPI_Reduce)完全取決於您使用的實現。 您可能會使用點對點通信方法設計廣播,該方法的性能要比給定的MPI_Bcast好。

無論如何,您必須考慮這些功能的每個功能。 廣播是從一個過程中獲取信息,然后將其發送給所有其他過程。 reduce是從每個過程中獲取信息並將其簡化為一個過程。 根據(最新) 標准 ,MPI_Bcast被認為是一對一的集體操作,而MPI_Reduce被認為是一對一的集體操作。 因此,在兩種實現中都可能找到有關將二進制樹用於MPI_Reduce的直覺。 但是,它很可能在MPI_Bcast中找不到。 可能是這樣的情況,MPI_Bcast是使用非阻塞點對點通信(從包含信息的進程發送到所有其他進程)並在通信后全部等待來實現的。 無論如何,為了弄清楚這兩個函數是如何工作的,建議您深入研究您的OpenMPI和MPICH2實現的源代碼。

正如Hristo所說,這取決於緩沖區的大小。 如果要發送一個較大的緩沖區,廣播將不得不進行大量的大型發送,而接收操作會對緩沖區進行一些本地操作以將其減小為單個值,然后僅發送該值而不是整個緩沖區。

暫無
暫無

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

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