Как правильно установить аргументы «количество отправок» и «смещение» в MPI_scatterv? - PullRequest
0 голосов
/ 03 апреля 2019

Я пытаюсь разделить строки двухмерного массива между «n» процессами, используя MPI_Scatterv.Два аргумента, которые останавливают меня, это «send_counts» и «смещения».Я знаю определение учебника о том, что делают эти массивы, но мне нужен способ динамически создавать эти массивы, чтобы принимать любой двумерный массив длины, особенно строки двумерного массива, которые не делятся равномерно по количеству процессов.

Вдохновение этого подхода исходит отсюда (создание массива send_counts имещение): https://gist.github.com/ehamberg/1263868 Я понимаю этот подход, но мне интересно, работает ли эта реализация только для даже двумерных массивов (матриц).

вопросы: Может ли проблема быть связана с тем, что двумерный массив не является смежным?

Являются ли правильные смещения относительно блоков памяти рассматриваемого типа данных (т. Е. Должны ли мои смещения быть 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 голосов
/ 03 апреля 2019

Проблема в том, что у вас есть несоответствующие подписи между тем, что вы отправляете (например, sendcounts и sendtype), и тем, что вы получаете (например, recvcount и recvtype).

В вашем случае, поскольку вы получаете (жестко запрограммировано) 100 MPI_FLOAT и отправляете MPI_FLOAT, оно может работать, только если все send_counts[i] == 100.

Полагаю, правильным решением является изменение значения recvcount.Для ранга i он должен иметь то же значение, что и send_counts[i] для корневого ранга (например, ранг 0 в вашем случае)

...