我试图使用MPI_Scatterv在“n”进程之间拆分二维数组的行。阻止我的两个论点是“send_counts”和“displacements”。我知道这些数组的教科书定义,但我需要一种动态创建这些数组的方法来接受任何长度的二维数组,尤其是2D数组的行,这些行不能被进程数整除。
这种方法的灵感来自于此处(构建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”进程打印出传递数组的一部分行。
这是我得到的错误:
在进程[2187067393,0]上报告的MPI_Scatterv在通信器MPI_COMM_WORLD上发生错误MPI_ERR_TRUNCATE:消息截断MPI_ERRORS_ARE_FATAL(此通信器中的进程现在将中止,并且可能是您的MPI作业)
**注意:数据文件是75行,每行有5个浮点数,逗号分隔
问题是你发送的内容(例如sendcounts
和sendtype
)与你收到的内容(例如recvcount
和recvtype
)之间存在不匹配的签名。
在你的情况下,因为你收到(硬编码)100 MPI_FLOAT
并且你发送MPI_FLOAT
,它只能在所有send_counts[i] == 100
工作。
我想正确的解决办法是改变recvcount
的价值。在排名i
上,它应该与根级别上的send_counts[i]
具有相同的值(例如,在您的情况下排名0
)