【问题标题】:MPI - Send a std::vector<string> to another group of processMPI - 将 std::vector<string> 发送到另一组进程
【发布时间】:2023-03-24 13:54:02
【问题描述】:

我正在尝试将向量发送到使用 MPI_Comm_spawn 创建的一组进程。我已经尝试了互联网上的所有内容,但我还没有解决它. 到目前为止,我设法让这些单独的组进行通信,并且家长会向工作人员发送一个 int。我需要让它与 std::vector 一起工作

给家长

#include <stdio.h>
#include <string.h>
#include "mpi.h"

int main(int argc, char* argv[]) {
    int i;
    int my_rank; /* rank of process */
    int p; /* number of processes */

    /* start up MPI */
    MPI_Init(&argc, &argv);

    /* find out process rank */
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

    /* find out number of processes */
    MPI_Comm_size(MPI_COMM_WORLD, &p);

    MPI_Group grp_world;
    MPI_Group grp_new;
    MPI_Comm newComm;

    MPI_Comm_group(MPI_COMM_WORLD, &grp_world); // get the group of processes for MPI_COMM_WORLD communicator

    MPI_Group_incl(grp_world, 1, &my_rank, &grp_new); // create a new group with only one member (my_rank process)

    MPI_Comm_create(MPI_COMM_WORLD, grp_new, &newComm); // create a new communicator for the new group

    int my_rank_grp; /* rank of process in grp_new */
    int p_grp; /* number of processes in grp_new */
    /* find out process rank in the new group */
    MPI_Comm_rank(newComm, &my_rank_grp);
    /* find out number of processes of the new group */
    MPI_Comm_size(newComm, &p_grp);

    printf("Process rank/size in WORLD/OWN GROUP: [%d/%d]/[%d/%d]\n",
            my_rank, p, my_rank_grp, p_grp);

    MPI_Comm workercomm; // intercommunicator
    int b = my_rank; // some data to be sent

    //[!!!] due to some MPI implementation problems, parallel calls the MPI_Comm_spawn trigger an error, so for the moment we just serialize these calls.
    for (i = 0; i < p; ++i) {
        if (i == my_rank) {
            MPI_Comm_spawn("/home/workspace_test/worker/Debug/worker",
                    MPI_ARGV_NULL, 3, MPI_INFO_NULL, 0, newComm, &workercomm,
                    MPI_ERRCODES_IGNORE );
        }
        MPI_Barrier(MPI_COMM_WORLD );
    }

    /* collective communication sample */
    MPI_Bcast(&b, 1, MPI_INT, MPI_ROOT, workercomm);
    MPI_Comm_free(&workercomm);

    /* shut down MPI */
    MPI_Finalize();

    return 0;
}

在这之后我有一个简单的工人:

#include <stdio.h>
#include <string.h>
#include "mpi.h"

int main(int argc, char* argv[]) {
    int my_rank; /* rank of process */
    int p; /* number of processes */
    int p_remote; /* number of processes in parent group */

    /* start up MPI */
    MPI_Init(&argc, &argv);

    /* find out process rank */
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

    /* find out number of processes */
    MPI_Comm_size(MPI_COMM_WORLD, &p);

    MPI_Comm parentcomm; // intercommunicator
    int b; // some data to be received

    MPI_Comm_get_parent(&parentcomm);

    /* find out number of processes in parent group */
    MPI_Comm_remote_size(parentcomm, &p_remote);


    MPI_Bcast(&b, 1, MPI_INT, 0, parentcomm);

    printf("[%d] Worker process: %d. Parent group size: %d!\n", b, my_rank, p_remote);

    MPI_Comm_free(&parentcomm);

    /* shut down MPI */
    MPI_Finalize();

    return 0;
}

这个简单的 int Bcast 一切都很好,但是如果我尝试发送一个向量,事情就不会像我期望的那样工作。

我想做什么?

我有一个带有路径的向量(来自磁盘的文件),路径数将除以进程数。每个进程都会收到一个文件块,每个文件的这个进程都会启动一个工作进程,对文件进行一些验证。

我到现在为止的尝试:

  • 我已经阅读并知道 MPI 没有类似 MPI_STRING 的东西,但如果我将字符串转换为 char* 情况也不会更好。
  • 我已经尝试过 std::vector/std::String in MPI 这个 prezentation 中的想法,但我仍然有一些问题。

也许对 mpi 有一定经验的人可以给我一些提示,告诉我如何发送整个向量。

谢谢。

//编辑

我尝试发送这样的数据: 一方:

std::vector<std::string> m_image_data2;
m_image_data2.push_back("test");
m_image_data2.push_back("test");
m_image_data2.push_back("test");
m_image_data2.push_back("test");
m_image_data2.push_back("test");
char* data = const_cast<char*>(m_image_data2[0].c_str());
MPI_Bcast(data, 5, MPI_CHAR, MPI_ROOT, workercomm);
MPI_Comm_free(&workercomm);

在工人方面:

/* find out number of processes in parent group */
MPI_Comm_remote_size(parentcomm, &p_remote);
std::vector<std::string> m_image_data2;
MPI_Bcast(&m_image_data2, 5, MPI_CHAR, 0, parentcomm);

所以当我尝试在生成的任务之间发送字符串向量时,我的问题现在出现了。

【问题讨论】:

  • 你的问题太吵了。创建一个MCVE - 最小、完整、可验证的示例。产卵部分真的需要吗? (我的猜测 - 它不是。但是通过删除它并找出答案,您将更接近解决方案)。您尝试了哪些字符串的使用,哪些不起作用?显示代码并显示错误。现在,缺少太多信息。如果您想获得有用的答案,请让问题更加专注于确切的问题。
  • 作为风格问题,您可以使用MPI_COMM_SELF 而不是(次优创建)newComm
  • @GillesGouaillardet 不是重复的。我不知道 MPI_Comm_spawn 创建的进程的 ID。所以我不使用 MPI_Send。
  • 如前所述,您应该真正为每个问题构建一个minimal reproducible example。那么你的问题是什么?在两个进程之间发送一个字符串向量(在这种情况下,您的问题实际上是MPI_Send()MPI_Recv())?向衍生任务发送一个整数?在这种情况下,您的问题在于交互器?

标签: c++ mpi


【解决方案1】:

检查以下代码以查看您的错误。

ma​​ster.cpp

#include <stdio.h>
#include <string>
#include <mpi.h>
#include <vector>
#include <cstring>

// Converts vector<string> to vector<char>.
std::vector<char> string_to_char(const std::vector<std::string>& strings) {
    std::vector<char> cstrings;
    cstrings.reserve(strings.size());
    for(std::string s: strings)
    {
        for(size_t i = 0; i < strlen(s.c_str()); ++i)
        {
            cstrings.push_back(s.c_str()[i]);
        }
    }

    return cstrings;
}

int main(int argc, char* argv[]) {
    ...
    std::vector<char> cstrings = string_to_char(m_image_data2);
    MPI_Bcast(cstrings.data(), cstrings.size(), MPI_CHAR, MPI_ROOT, workercomm);
    ...
}

worker.cpp

#include <stdio.h>
#include <string>
#include <mpi.h>
#include <vector>

int main(int argc, char* argv[]) {
    ...    
    std::vector<char> cstrings(20);
    MPI_Bcast(cstrings.data(), 20, MPI_CHAR, 0, parentcomm);

    // cstrings: testtesttesttesttest
    // print first four chars.
    printf("Worker process: %c%c%c%c\n", cstrings[0], cstrings[1], cstrings[2], cstrings[3]);
    ...
}

【讨论】:

  • 这是一个很大的变化。我在想将当前字符串转换为 const char* 就足够了,但从你的例子中我明白这不是。我设法通过在创建向量时将整个向量作为命令行传递来将向量发送到工作进程。你的例子更干净,更好。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-26
  • 2014-01-11
  • 2012-05-23
  • 2011-02-09
  • 1970-01-01
  • 2017-09-21
  • 1970-01-01
相关资源
最近更新 更多