Тупик, вызванный связью точка-точка в MPI с использованием цикла для отправки от мастера к детям - PullRequest
2 голосов
/ 08 апреля 2019

Я пытаюсь решить домашнюю задачу, чтобы отладить следующий модульный тест.

По сути, главный процесс генерирует случайные целые числа и отправляет их дочерним процессам для проверки простоты, результат передается обратно в главный процесс, и алгоритм завершается.

Я знаю, что петли должны быть заменены коллективным общением, однако это другая часть вопроса. Я хочу понять, почему этот код, который у меня есть, вызывает тупик.

Из прочтения других вопросов я знаю, что количество отправленных / полученных сообщений должно совпадать. Однако я не вижу, как это не так в моем коде.

Текущее поведение заключается в том, что простое число найдено, отправлено обратно в главный процесс, после чего программа просто зависает - пока она не будет отменена вручную с помощью 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;
}

1 Ответ

1 голос
/ 08 апреля 2019

Я ничего не знаю о MPI, но в вашем коде, если rank != 0, цикл while никогда не может быть завершен, потому что found_prime никогда не устанавливается в ветви elserank тоже никогда не изменяется).

Edit:

Как сказал @DanielLangr, рабам нужен способ узнать, что больше нет работы, чтобы приходить и выходить (цикл).

...