【问题标题】:MPI_Bcast c++ STL vectorMPI_Bcast c++ STL 向量
【发布时间】:2018-07-18 18:21:05
【问题描述】:

为什么下面的代码不起作用?它适用于我的用户定义类,但不适用于 STL 向量。

std::vector<int> v(4);
MPI_Bcast(&v, sizeof(v), MPI_BYTE, 0, MPI_COMM_WORLD);

我收到分段错误:

[sdg:13611] Signal: Segmentation fault (11)
[sdg:13611] Signal code: Address not mapped (1)

既然vector中的元素是连续存储的,为什么我不能使用MPI_BYTE将std::vector作为一个整体发送?

【问题讨论】:

  • 这个问题经常被问到很多变种,但我没有找到合适的重复。所以我尝试添加一个规范的答案。

标签: c++ parallel-processing stl mpi


【解决方案1】:

vector 本身的地址与data 的地址不同。像您提议的那样发送对象仅适用于普通可复制类型 - 您可以想象 MPI 通信的工作方式类似于 memcpy。你可以检查std::is_trivially_copyable - std::vector 本身永远不会轻易复制

但是,vector 将其 data 存储在连续内存中 - 您可以在其上使用 memcpy

您必须确保所有 MPI 进程在操作之前都有一个具有相同size 的向量capacity 是不够的。如果您只知道一个进程上的size,则必须在另一个进程上相应地广播之前的大小和resize 目标向量。

此外,向量中的元素本身必须可轻松复制

MPI_Bcast(v.data(), v.size(), MPI_INT, 0, MPI_COMM_WORLD);

如果由于某种原因您无法确定 MPI 类型(例如 MPI_INT),您可以按照以下方式进行操作(避免在更改类型时中断的冗余)。

MPI_Bcast(v.data(), v.size() * sizeof(decltype(v)::value_type)), MPI_BYTE, 0, MPI_COMM_WORLD);

【讨论】:

    【解决方案2】:

    你很可能想要

    if (!v.empty())
        MPI_Bcast(&v[0], v.size() * sizeof(decltype(v)::value_type)), MPI_BYTE, 0, MPI_COMM_WORLD);
    

    【讨论】:

    • 可以的。但我想写一个通用函数来 Bcast 任何对象。 MPI_Bcast(&amp;foo, sizeof(foo), MPI_BYTE, 0, MPI_COMM_WORLD) 适用于我知道的大多数类,但不适用于 std::vector。
    • 这种情况是一个糟糕的陷阱,会引发错误,其中v 在某些等级上为空。
    • 祖蓝:这就是为什么第一行代码检查 v 是否为空,如果是则不调用 MPI_Bcast 的 API。
    • user27490: sizeof(foo) 不起作用。一个向量通常是 3 个指针。因此,对于 32 位,您将获得 12 位,对于 64 位,您将获得 24 位,无论向量管理多少项。向量的真实大小总是 v.size() * sizeof(underlying type)
    • @SJHowe MPI_Bcast() 是一个集体操作,因此必须由通信器的所有等级调用。一个直接的结果是v.size()(因此v.empty())在所有等级上必须相同,这由程序员来确保。如果v 在某些但不是所有等级上为空,您的应用程序可能最终会挂起,可能在其他位置,这使得故障排除非常困难。另一方面,如果v.size() 不完全相同,您的应用程序可能会在MPI_Bcast() 中崩溃,这更容易调试。
    猜你喜欢
    • 1970-01-01
    • 2018-10-10
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 2016-04-01
    • 1970-01-01
    相关资源
    最近更新 更多