如何在MPI_Send中发送设置对象 [英] How to send a set object in MPI_Send

查看:126
本文介绍了如何在MPI_Send中发送设置对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我搜索发送一个设置对象,最近我发现是向量(它不同,不使用集)。

I searched to send a set object and the closest I found was with vector (it's different and don't work with set).

如何发送在MPI_Send中设置对象? (不使用boost库)任何人都可以放一个简单的例子?

How can I send a set object in MPI_Send? (without using boost library) Anyone can put a simple example?

推荐答案

是否必须写一个复杂的数据结构或者通过网络在MPI中,问题是一样的;您必须将数据提取到普通旧数据(POD)中,保存,然后输出,同样可以将保存的数据解压缩为相同类型的结构。一般来说,这被称为序列化。

Whether you have to write a complex data structure to a file or over the network in MPI, the issues are the same; you have to extract the data into "Plain Old Data" (POD), save it, and then output it, and likewise be able to unpack the saved data into the same sort of structure. In general, this is called serialization.

对于任何给定的结构,你总是可以编写自己的例程,但在C ++中,Boost中有一个框架, a href =http://www.boost.org/doc/libs/1_58_0/libs/serialization/doc/index.html =nofollow> Boost Serialization Library ;它对于这个例子有点重量,但它将适用于大多数(所有?)STL容器,并有钩子为您自己的类添加支持。

For any given structure you can always write your own routines for doing this, but in C++, there's a framework in Boost called the Boost Serialization Library for doing this; it's a bit heavyweight for this example but it will work for most (all?) STL containers and there are hooks for adding support for your own classes.

主要技巧使用Boost这一点是Boost库(和所有的例子)使它很容易写入数据到文件,但在这里你想保存在内存中并通过网络发送/接收它;这意味着跳过一对夫妇更多的箍,以确保序列化是一个可以访问的数组。 此SO回答在这方面非常有帮助。

The main trick with using Boost for this is that the Boost libraries (and all the examples) make it very easy to write the data to a file, but here you want to keep it in memory and send/receive it over the network; that means jumping through a couple more hoops to make sure the serialization is into an array you can access. This SO answer is very helpful in this regard.

因此一个完整的工作示例如下所示:

So a complete working example looks like this:

#include <mpi.h>
#include <set>
#include <string>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/set.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/back_inserter.hpp>

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

    int size, rank;

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

    if (size < 2) {
        if (rank == 0)
            std::cerr << "Require at least 2 tasks" << std::endl;
        MPI_Abort(MPI_COMM_WORLD, 1);
    }

   const int lentag=0;
   const int datatag=1;
   if (rank == 0) {
        int nums[] = {1,4,9,16};
        std::set<int> send_set(nums, nums+4);

        std::cout << "Rank " << rank << " sending set: ";
        for (std::set<int>::iterator i=send_set.begin(); i!=send_set.end(); i++)
            std::cout << *i << " ";
        std::cout << std::endl;

        // We're going to serialize into a std::string of bytes, and then send this
        std::string serial_str;
        boost::iostreams::back_insert_device<std::string> inserter(serial_str);
        boost::iostreams::stream<boost::iostreams::back_insert_device<std::string> > s(inserter);
        boost::archive::binary_oarchive send_ar(s);

        send_ar << send_set;
        s.flush();
        int len = serial_str.size();

        // Send length, then data
        MPI_Send( &len, 1, MPI_INT, 1, lentag, MPI_COMM_WORLD );
        MPI_Send( (void *)serial_str.data(), len, MPI_BYTE, 1, datatag, MPI_COMM_WORLD );
    } else if (rank == 1) {
        int len;
        MPI_Recv( &len, 1, MPI_INT, 0, lentag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        char data[len+1];
        MPI_Recv( data, len, MPI_BYTE, 0, datatag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        data[len] = '\0';

        boost::iostreams::basic_array_source<char> device(data, len);
        boost::iostreams::stream<boost::iostreams::basic_array_source<char> > s(device);
        boost::archive::binary_iarchive recv_ar(s);

        std::set<int> recv_set;
        recv_ar >> recv_set;

        std::cout << "Rank " << rank << " got set: ";
        for (std::set<int>::iterator i=recv_set.begin(); i!=recv_set.end(); i++)
            std::cout << *i << " ";
        std::cout << std::endl;
    }

    MPI_Finalize();
    return 0;
}

运行时:

$ mpic++ mpi-set.cxx -o mpiset -lboost_serialization
$ mpirun -np 2 ./mpiset
Rank 0 sending set: 1 4 9 16
Rank 1 got set: 1 4 9 16

如果你真的不想使用Boost ,因为你实际上不能直接看到集合的数据结构,没有太多的选择,但提取数据到数组或向量,并发送数据的方式:

If you really don't want to use Boost, since you can't actually see directly into the set data structure, there's not much alternative but to extract the data into an array or vector, and send the data that way:

#include <mpi.h>
#include <set>
#include <vector>

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

    int size, rank;

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

    if (size < 2) {
        if (rank == 0)
            std::cerr << "Require at least 2 tasks" << std::endl;
        MPI_Abort(MPI_COMM_WORLD, 1);
    }

   const int lentag=0;
   const int datatag=1;
   if (rank == 0) {
        int nums[] = {1,4,9,16};
        std::set<int> send_set(nums, nums+4);

        std::cout << "Rank " << rank << " sending set: ";
        for (std::set<int>::iterator i=send_set.begin(); i!=send_set.end(); i++)
            std::cout << *i << " ";
        std::cout << std::endl;

        // Send length, then data
        int len = send_set.size();
        MPI_Send( &len, 1, MPI_INT, 1, lentag, MPI_COMM_WORLD );

        std::vector<int> send_vec;
        for (std::set<int>::iterator i=send_set.begin(); i!=send_set.end(); i++) 
            send_vec.push_back(*i);

        MPI_Send( send_vec.data(), len, MPI_INT, 1, datatag, MPI_COMM_WORLD );

    } else if (rank == 1) {

        int len;
        MPI_Recv( &len, 1, MPI_INT, 0, lentag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        int recv_data[len];
        MPI_Recv( recv_data, len, MPI_INT, 0, datatag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        std::set<int> recv_set;
        for (int i=0; i<len; i++) 
            recv_set.insert(recv_data[i]);

        std::cout << "Rank " << rank << " got set: ";
        for (std::set<int>::iterator i=recv_set.begin(); i!=recv_set.end(); i++)
            std::cout << *i << " ";
        std::cout << std::endl;
    }

    MPI_Finalize();
    return 0;
}

运行时:

$ mpicxx -o mpisetvector mpi-set-vector.cxx 
$ mpirun -np 2 mpisetvector
Rank 0 sending set: 1 4 9 16 
Rank 1 got set: 1 4 9 16 

但真的,如果你要去做这与其他类型的对象,Boost是要走的路。

But really, if you're going to be doing this with other types of object as well, Boost is the way to go.

这篇关于如何在MPI_Send中发送设置对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆