You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

一维std::vector的Boost序列化故障求助

问题排查与修复

核心故障原因分析

你的代码触发段错误主要源于以下几个关键问题:

  • 非阻塞请求被覆盖丢失:循环中每次调用irecv都将结果赋值给同一个req对象,前一次的请求会被销毁,导致未完成的MPI通信引用失效,触发内存访问错误。
  • 未等待通信完成就退出:req.test()仅检查请求是否完成,不会阻塞等待所有通信结束,程序直接return会导致MPI通信资源未正确释放,引发段错误。
  • 收发对象容器尺寸不匹配:发送端TobeSend中的Dummy对象包含2个元素的vector,但接收端TobeRecvd的Dummy只有1个元素,反序列化时会尝试写入超出初始容量的内存,触发越界访问。

修复后的代码

#include <iostream>
#include <vector>
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/mpi.hpp>
#include <boost/version.hpp>

class Dummy
{
private:
    std::vector<unsigned int> array;
    friend class boost::serialization::access;
    template <class T> 
    inline void serialize(T & ar, const unsigned int /*version*/)
    {
        ar & array;
    }
public:
    Dummy() = default;
    explicit Dummy(const int nDivs) 
    {
        array.resize(nDivs);
    }
    ~Dummy() = default; 
};

int main(int argc, char* const argv[]) 
{
    boost::mpi::environment   env(argc, argv); 
    boost::mpi::communicator  world;

    std::cout << "Using Boost "      
              << BOOST_VERSION / 100000     << "."  // major version
              << BOOST_VERSION / 100 % 1000 << "."  // minor version
              << BOOST_VERSION % 100                // patch level
              << " (Rank: " << world.rank() << ")" << std::endl;

    const int tag = 0;
    const std::size_t size = 10000;  
    const std::vector<int> neighbrs = {0, 1, 2, 3};

    // 发送端对象:每个Dummy包含2个元素的vector
    std::vector<Dummy> TobeSend;
    TobeSend.reserve(size);
    for (std::size_t i = 0; i < size; ++i)
    {
        TobeSend.emplace_back(2);
    }

    // 接收端对象:默认构造,Boost序列化会自动处理vector的大小
    std::vector<Dummy> TobeRecvd(size);

    std::vector<boost::mpi::request> requests;

    // 发起所有非阻塞发送请求
    for (int target : neighbrs)
    {
        if (world.rank() != target)
        {
            requests.push_back(world.isend(target, tag, TobeSend));
        }
    }

    // 发起所有非阻塞接收请求
    for (int source : neighbrs)
    {
        if (world.rank() != source)
        {
            requests.push_back(world.irecv(source, tag, TobeRecvd));
        }
    }

    // 等待所有通信请求完成
    boost::mpi::wait_all(requests.begin(), requests.end());

    return 0; 
}

关键修复说明

  1. 管理所有MPI请求:用std::vector<boost::mpi::request>存储所有isend和irecv的请求,避免单个请求对象覆盖导致的资源丢失。
  2. 等待通信完成:调用boost::mpi::wait_all确保所有非阻塞通信完成后再退出程序,避免未完成的通信引发的资源错误。
  3. 统一收发对象初始化:接收端TobeRecvd使用默认构造的Dummy对象,Boost序列化会自动根据发送的数据调整vector的大小,避免初始尺寸不匹配导致的内存越界。
  4. 优化对象构造:用emplace_back构造TobeSend,减少不必要的对象拷贝,提升性能并避免潜在的拷贝错误。
  5. 完善MPI环境初始化:显式传递argc和argv给boost::mpi::environment,符合MPI标准初始化流程。

编译命令

保持原编译命令不变:

mpic++ -g mpidatatype.cpp -o output -lboost_mpi -lboost_serialization

内容的提问来源于stack exchange,提问作者MA19

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:07:06