Как отправить и получить переменную длину (зависит от процессора) std :: vector <myStruct>с использованием MPI - PullRequest
3 голосов
/ 20 июня 2019

У меня есть вектор пользовательских структур, живущих на каждом процессоре.Эти векторы имеют разные размеры.Я изо всех сил пытаюсь получить данные от процессоров 1 до N на процессоре 0.

Я попытался реализовать рекомендации на страницах 31-33 прилагаемого слайд-шоу, где отправляются и принимаются std :: vector.Я также реализовал MPI_register и MPI_deregister.

Я компилирую и запускаю этот код на osx.

https://www.sharcnet.ca/help/images/f/fa/MPI_Datatypes_with_Opaque_Types_seminar_2014.pdf

#include <mpi.h>
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <cstddef>

struct crab_claw
{
    crab_claw()  : com(), number(), weight(), crossing_count(), com0_id() {}
    /////////
    crab_claw(
             std::vector<double> c,
             int n,
             double w,
             std::vector<double> cc,
             int id
             ) : com( c ), number( n ), weight( w ), crossing_count( cc ), com0_id( id ) {}
    std::vector<double> com = std::vector<double>(3);
    int number;
    double weight;
    std::vector<double> crossing_count = std::vector<double>(3);
    int com0_id;
};

MPI_Datatype register_mpi_type(crab_claw)// const&)
{
    constexpr std::size_t num_members = 5;
    int lengths[num_members] = {3,1,1,3,1};

    MPI_Aint offsets[num_members] =  {
                                      offsetof(crab_claw, com), //vector (of doubles)
                                      offsetof(crab_claw, number),     //int
                                      offsetof(crab_claw, weight),     //double
                                      offsetof(crab_claw, crossing_count),       //vector (of doubles)
                                      offsetof(crab_claw, com0_id)  //int
                                      };

    MPI_Datatype types[num_members] = { MPI_DOUBLE, MPI_INT, MPI_DOUBLE, MPI_DOUBLE, MPI_INT };
    MPI_Datatype type;
    MPI_Type_struct(num_members, lengths, offsets, types, &type);
    MPI_Type_commit(&type);
    return type;
}

void deregister_mpi_type(MPI_Datatype type)
{
    MPI_Type_free(&type);
}

int main(
         int argc,
         char* argv[]
         )
{
    MPI_Init(&argc, &argv);
    int mpi_nprocessors;  MPI_Comm_size(MPI_COMM_WORLD, &mpi_nprocessors);
    int mpi_my_id;        MPI_Comm_rank(MPI_COMM_WORLD, &mpi_my_id);
    const int mpi_master_id = 0;

    std::vector<crab_claw> h; double j = mpi_my_id;

    for(int i = 0; i < (2*mpi_my_id+1); ++i)
    {
        crab_claw h_1;
        std::vector<double> h_com(3,0.);
        h_com[0] = ((i+1)/20. * 2*j)/(i+1);
        h_com[1] = ((i+1)/20. * 2*j)/(i+1);
        h_com[2] = ((i+1)/20. * 2*j)/(i+1);
        j /= 0.5;
        std::vector<double> crossing_count(3,0.);

        h_1.com            = h_com;
        h_1.number         = i*mpi_my_id+1;
        h_1.weight         = j*0.3;
        h_1.crossing_count = crossing_count;
        h_1.com0_id        = mpi_my_id;
        h.push_back(h_1);
    }

    MPI_Barrier(MPI_COMM_WORLD);
    /* create a type for struct crab_claw */

    std::vector<crab_claw> storage;

    MPI_Datatype type = register_mpi_type(h[0]);
    if (mpi_my_id != mpi_master_id)
    {
        int       tag    = mpi_my_id;
        unsigned length = h.size();
        const int destination = mpi_master_id;
        MPI_Send(
                 &length,
                 1,
                 MPI_UNSIGNED,
                 destination,
                 tag+mpi_nprocessors,
                 MPI_COMM_WORLD
                 );

        if(length != 0)
        {
            MPI_Send(
                     h.data(),
                     length,
                     type,
                     destination,
                     mpi_my_id,
                     MPI_COMM_WORLD
                     );
        }
    }

    MPI_Barrier(MPI_COMM_WORLD);
    if (mpi_my_id == mpi_master_id)
    {
        for(int j = 0; j < mpi_nprocessors; ++j)
        {
            if(j == 0)
            {
                storage.insert(storage.end(), h.begin(), h.end());

                std::cout << "inert insert" << '\n';
            }

            if(j > 0)
            {
                unsigned length;
                MPI_Status s;

                MPI_Recv(
                         &length,
                         1,
                         MPI_UNSIGNED,
                         j,
                         j+mpi_nprocessors,
                         MPI_COMM_WORLD,
                         &s
                         );

                std::vector<crab_claw> rec;

                //std::cout << "MPIMYID " << mpi_my_id << " LENGTH OF RECEIVED OBJ " << length << " j " << j << '\n';

                if (length != 0)
                {
                    h.resize(length);
                    MPI_Recv(
                             h.data(),
                             length,
                             type,
                             j,
                             j,
                             MPI_COMM_WORLD,
                             &s
                             );


                    std::cout << "SIZE() " << h.size() << " MY MPI ID " << mpi_my_id << " h[0].number " << h[0].weight << '\n';


                //storage.insert(storage.end(), h.begin(), h.end());

                } else
                {
                    h.clear();
                }

            }
        }
    }


    //std::cout << mpi_my_id << '\n';
    MPI_Finalize();
    return 0;
}

Это ошибка, которую я получаю,Я думаю, что это говорит о том, что данные от h, отправленные кем-либо, кроме главного процессора, освобождаются без выделения?

параллельный (32428,0x7fff7d3e6000) malloc: * ошибка для объекта 0x7fcb2bf07d10: указатель освобождаетсяне было выделено * установить точку останова в malloc_error_break для отладки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...