【问题标题】:Cant send the whole vector through MPI_send无法通过 MPI_send 发送整个向量
【发布时间】:2016-06-14 08:24:57
【问题描述】:

我一直在努力学习 MPI。当我尝试运行以下代码时,我得到了错误的输出。

if (world_rank == 0){

    vector<vector<double> > n(4,vector<double>(4));

    srand(time(NULL));

    for(int i=0; i<4 ;i++){
        for(int j=0;j<4;j++){
            n[i][j] = (double)rand()/RAND_MAX;
            cout << n[i][j] << " ";
        }
        cout << endl;
    }
    MPI_Send((void*)&n[0][0],16*sizeof(double),MPI_BYTE,1,0,MPI_COMM_WORLD);
}else{
    MPI_Status status;

    vector<vector<double> > n(4,vector<double>(4));

    MPI_Probe(0,0,MPI_COMM_WORLD,&status);

    int size;

    MPI_Get_count(&status,MPI_BYTE,&size);

    cout << endl << size << endl;

    MPI_Recv((void*)&n[0][0],16*sizeof(n[0][0]),MPI_BYTE,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);

    cout.flush();
    cout << endl;

    for(int i=0; i<4 ;i++){
        for(int j=0;j<4;j++){
            cout << n[i][j] << " ";
        }
        cout << endl;
    }
}

我得到除了最后 3 个以外的所有双精度值。 像这样。

0.824468 0.752417 0.757125 0.470763 
0.251683 0.703306 0.157991 0.764423 
0.815327 0.0402807 0.897109 0.313816 
0.997203 0.796665 0.0522305 0.797733 

128

0.824468 0.752417 0.757125 0.470763 
0.251683 0.703306 0.157991 0.764423 
0.815327 0.0402807 0.897109 0.313816 
0.997203 0 0 0

谁能告诉我为什么会这样? 我运行相同的代码大约一百次,仍然得到相同的输出(当然有不同的值),但最后三个总是 0。

但是当我将大小从 16 更改为 19 时,我得到了所有值。

我还有一个疑问。 有时输出(来自节点 0 和 1 的值)会重叠。谁能告诉我如何阻止这种情况,或者至少解释一下为什么会发生这种情况。我的意思是即使 send 和 recv 是阻塞函数。如何在节点 0 之前打印节点 1 的输出

【问题讨论】:

    标签: c++ mpi


    【解决方案1】:

    您将二维数据n 定义为vector&lt;vector&lt;double&gt; &gt; 使其在内存中不连续。因此,您不能简单地使用 MPI 传输它(有一些方法可以做到,但您最好只是让内存连续)。

    为了让你的记忆连续,你可以像这样声明你的n(未经测试):

    vector<double> ndata(4*4); //contiguous storage of the actual data
    vector<double*> n(4);      //vector of pointers to access the actual data
    for (int i=1; i<4; i++)    //initialisation of the pointers to the data
        n[i] = &ndata[4*i];
    

    当然,有更好的方法在 C++ 中为多维数组定义连续存储,但这只是解决您当前问题的快速解决方案。例如,请参阅 this answer 以获得更好的结构。

    顺便说一句,您的MPI_Send()MPI_Recv() 调用应该使用4*4 MPI_DOUBLE 而不是4*4*sizeof(double) MPI_BYTE

    【讨论】:

    • 谢谢,我知道了,我只是在试验它。你能告诉我我问的另一件事吗(这就是为什么两个节点的输出在屏幕上重叠。)。有没有办法阻止它。我知道两个节点可能在不同时间位于代码的不同部分,但是因为 send 和 recv 命令都被阻塞了。接收打印后写入的内容如何比发送前打印的内容更早。如果你能回答这个问题,我就可以安息了。谢谢。
    • 对于交错打印,这只是各种进程之间的竞争条件以及操作系统对输出的缓冲问题。有关更多详细信息,请参阅this
    • 我读了你的链接。我知道那部分。但就像说的那样,我需要某种互斥或障碍来控制对吗?这就是这里发生的事情。我在发送数据之前打印,然后在收到数据后再次打印。所以只有在节点 0 打印之后,我才会发送数据(在此节点 1 保持阻塞期间),并且在节点 1 接收到数据之后,它可以打印发送的数据。但有时我会在节点 0 打印之前打印发送的数据。
    • 您不能强制并行打印的顺序。即使有一些障碍来同步你的进程,OS / fs / 任何东西都可以重新排序它......所以除非你打印到一个文件中并使用 MPI-IO 来确保来自不同线程的各种贡献被放置在正确的位置,你无法强制执行打印顺序...
    猜你喜欢
    • 2013-12-06
    • 2018-03-08
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    相关资源
    最近更新 更多