【问题标题】:Deadlock caused by point-to-point communication in MPI, using a loop to send from master to childrenMPI中点对点通信导致的死锁,使用循环从master发送给children
【发布时间】:2019-04-09 04:43:17
【问题描述】:

我正在尝试解决家庭作业问题以调试以下单元测试。

基本上主进程生成随机整数并发送给子进程检查素数,结果传回主进程,算法结束。

我知道应该用集体交流来代替循环,但这是问题的另一部分。我想了解为什么我在这里的这段代码会导致死锁。

通过阅读其他questions,我知道发送/接收的数量应该相互匹配。但是,我看不出在我的代码中情况并非如此。

当前的行为是找到一个素数,将其发送回主进程,此时程序会挂起 - 直到使用 ctrl-C 手动取消。

我知道这不是解决这个问题的惯用方法,但我真的很想知道这个方法中的错误到底在哪里。

谢谢!


TEST_CASE("3a - Finding prime numbers", "[MPI]" )
{
    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    // Random number generation
    std::minstd_rand generator;
    unsigned min(2342), max(12342340);
    std::uniform_int_distribution<> distribution(min, max);

    // candidates too big, one of the size values is the master node
    std::vector<unsigned> candidates(size - 1);

    // Main loop continues until a prime is found
    int found_prime(0);
    while (found_prime == 0) {


        if (rank == 0) {

            // Create some candidate numbers for each process to test
            std::generate(candidates.begin(), candidates.end(),
                          [&]() { return distribution(generator); });

            // Send one to each worker
            for (int worker(1); worker < size; ++worker) {
                int rc = MPI_Ssend(&candidates[worker - 1], 1, MPI_UNSIGNED,
                                   worker, 0, MPI_COMM_WORLD);
                REQUIRE(rc == MPI_SUCCESS);
            }

            // Receive whether it was prime
            for (int worker(1); worker < size; ++worker) {
                unsigned result;
                int rc = MPI_Recv(&result, 1, MPI_UNSIGNED, worker, 0,
                                  MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                REQUIRE(rc == MPI_SUCCESS);
                if (result == 1) {
                    found_prime = candidates[worker - 1];
                    std::cout << "Worker " << worker << " found prime "
                              << found_prime << std::endl;
                }
            }
        } else {
            // Receive the candidate to check
            unsigned candidate;
            int rc = MPI_Recv(&candidate, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD,
                              MPI_STATUS_IGNORE);
            REQUIRE(rc == MPI_SUCCESS);
            // Do the check
            unsigned is_prime = mp::IsPrime(candidate) ? 1 : 0;
            // Return the result
            rc = MPI_Ssend(&is_prime, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD);
            REQUIRE(rc == MPI_SUCCESS);
        }
    }
    std::cout << "Finished" << rank << std::endl;
}

【问题讨论】:

    标签: c++ parallel-processing mpi


    【解决方案1】:

    我对 MPI 一无所知,但在您的代码中,如果 rank != 0,则永远无法退出 while 循环,因为 found_prime 从未在 else 分支中设置(并且 rank 也从未更改)。

    编辑:

    正如@DanielLangr 所说,奴隶需要一种方法来发现没有更多的工作可以来和退出(循环)。

    【讨论】:

    • 在 MPI 中,排名表示进程,因此只要您有超过 1 个进程,else 将始终运行。
    • 不,所有进程都必须进入循环(否则发送/接收的数量不匹配)。但是,从属的循环永远不会结束,这是正确的。问题是其他进程不知道其中一个何时找到素数。然而,root 知道,所以你只需要向 slave 发送一些特殊的消息。 MPI 标签非常适合。
    • 哦,天哪,@DanielLangr 非常感谢,我已经为此烦恼了好几个小时。 :)
    • @skailasa 不客气。你可以在这里找到一些灵感:stackoverflow.com/a/10494108/580083.
    猜你喜欢
    • 2019-05-29
    • 2016-05-07
    • 1970-01-01
    • 2019-09-15
    • 2017-03-04
    • 2021-03-14
    • 2019-06-11
    • 2014-04-04
    • 2017-10-21
    相关资源
    最近更新 更多