如何正确设置MPI_scatterv中的“发送计数”和“位移”参数?

时间:2019-04-03 00:16:59

标签: c++ mpi distributed-computing openmpi

我正在尝试使用MPI_Scatterv在“ n”个进程之间拆分二维数组的行。阻止我的两个参数是“ send_counts”和“ displacements”。我知道这些数组的作用的教科书定义,但是我需要一种动态创建这些数组的方法,以接受任意长度的二维数组,尤其是二维数组的行数不能被进程数均匀除尽的行。

这种方法的灵感来自于这里(构建send_counts和置换数组): https://gist.github.com/ehamberg/1263868 我了解这种方法,但是我不知道这种实现是否仅适用于2D数组(矩阵)。

问题: 问题可能与2D阵列不连续有关吗?

有关数据类型的存储块的位移是否正确(即,由于浮点数是4个字节的内存,我的位移应为4吗?)

#include <iostream>
#include <fstream>
#include <sstream>
#include "mpi.h"
#include <stdio.h>


#define ROW 75 
#define COL 5

void importData(std::string str, float (*dest)[75][5], int length) {

std::ifstream infile(str);

int i = 0;
int j = 0;

std::string a;

while (getline(infile, a)) {

    std::stringstream ss(a);
    std::string token;
    i = 0;


    while (getline(ss, token, ',')) {

        if (i < length) {

            (*dest)[i][j] = strtof(token.c_str(), NULL);
        }

        else {

            i++;
        }

        j++;

    }


 }


}


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

float iris[75][5] = { {} };

importData("Iris.test", &iris, 5);


int rank, comm_sz;

int sum = 0;

int rem = (ROW*COL) % comm_sz;

int * send_counts;
int * displs;


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


int row[1000];




send_counts = (int *)malloc(sizeof(float)*comm_sz);
displs = (int *)malloc(sizeof(float)*comm_sz);


// calculate send counts and displacements
for (int i = 0; i < comm_sz; i++) {
    send_counts[i] = (ROW*ROW) / comm_sz;
    if (rem > 0) {
        send_counts[i]++;
        rem--;
    }

    displs[i] = sum;
    sum += send_counts[i];
}



if (rank == 0){


}


// Scatter the big table to everybody's little table, scattering the rows
MPI_Scatterv(iris, send_counts, displs, MPI_FLOAT, row, 100, MPI_FLOAT, 0, 
MPI_COMM_WORLD);
//                              displacements      recv buffer, recv count
std::cout << "%d: " << rank << std::endl;

for (int i = 0; i < send_counts[rank]; i++) {
    std::cout << "%f\t" << row[i] << std::endl;
}

MPI_Finalize();



}

我希望“ n”个进程中的每个进程都能打印出所传递数组的部分行。

这是我得到的错误:

MPI_Scatterv中发生错误 由过程报告[2187067393,0] 在通信器MPI_COMM_WORLD上 MPI_ERR_TRUNCATE:消息被截断 MPI_ERRORS_ARE_FATAL(此通信器中的进程现在将中止, 甚至可能是您的MPI工作)

**注意:数据文件为75行,每行有5个浮点数,以逗号分隔

1 个答案:

答案 0 :(得分:0)

问题是您在发送的内容(例如sendcountssendtype)和收到的内容(例如recvcountrecvtype之间具有不匹配的签名。< / p>

在您的情况下,由于您收到(硬编码)100 MPI_FLOAT并发送了MPI_FLOAT,因此只有所有send_counts[i] == 100都可以使用。

我认为正确的解决方法是更改​​recvcount的值。在等级i上,它的值应与根等级上的send_counts[i]相同(例如,在您的情况下,等级0