【问题标题】:Dinning philosophers problem MPI C++. Everytime process 0 exit without using finalize餐饮哲学家问题 MPI C++。每次进程 0 退出而不使用 finalize
【发布时间】:2021-03-22 09:46:17
【问题描述】:

我在解决问题时遇到了一些麻烦,我不知道该怎么做。每次编译此代码时,我都会收到相同的错误: “工作中止: [排名] 消息

[0] 进程没有调用 finalize 就退出了

[1-5] 终止

----错误分析-----

[0] 在 USER-PC 上 Philosophers.exe 提前结束并且可能已经崩溃。退出代码 0x80000003"

代码:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#include <list>
#include "mpi.h"
#define FORK_REQUEST 1
#define FORK_RESPONSE 2
#define FORK_RELEASE 3

int main(int argc, char** argv) {
    int rank;
    int size;
    //init MPI
    if (MPI_Init(&argc, &argv) != MPI_SUCCESS) {
        return 1;
    }
    if (MPI_Comm_size(MPI_COMM_WORLD, &size) != MPI_SUCCESS) {
        MPI_Finalize();
        return 2;
    }
    if (MPI_Comm_rank(MPI_COMM_WORLD, &rank) != MPI_SUCCESS) {
        MPI_Finalize();
        return 3;
    }

    if (!rank) {
        printf("Hello from table %d \n", rank);
        int in_buffer[1];
        int out_buffer[1];
        int philosopher;
        MPI_Status status;

        std::list<int> queue;

        bool* fork = new bool[size - 1];
        for (int i = 0; i < size - 1; i++) fork[i] = true; //Init all forks as free

        //Table main loop
        while (true) {
            MPI_Recv(in_buffer, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); // Recive next message
            philosopher = status.MPI_SOURCE; //Read source of message

            if (status.MPI_TAG == FORK_REQUEST) { //If Request for forks
                printf("Table got philosopher %d fork request\n", philosopher);
                if (fork[philosopher % (size - 1)] == true && fork[philosopher - 1] == true) { //If both forks are free
                    fork[philosopher % (size - 1)] = false; //Set the forks as taken
                    fork[philosopher - 1] = false;
                    MPI_Send(out_buffer, 1, MPI_REAL, philosopher, FORK_RESPONSE, MPI_COMM_WORLD); // Send Fork response to the right philosopher
                    printf("Table sent philosopher %d the forks\n", philosopher);
                }
                else //If not both forks are free
                    queue.push_back(philosopher); //Put in wait queue
            }
            if (status.MPI_TAG == FORK_RELEASE) { //If Release of forks
                fork[philosopher % (size - 1)] = true; //Set forks to free again
                fork[philosopher - 1] = true;
                printf("Table got philosopher %d fork release\n", philosopher);

                if (!queue.empty()) { //If philosopher whaiting for forks
                    for (std::list<int>::iterator it = queue.begin(); it != queue.end(); it++) { //Go through whole list of whaiting philosophers
                        philosopher = *it;
                        if (fork[philosopher % (size - 1)] == true && fork[philosopher - 1] == true) { //If one of them can get both forks
                            fork[philosopher % (size - 1)] = false;
                            fork[philosopher - 1] = false;
                            MPI_Send(out_buffer, 1, MPI_INT, philosopher, FORK_RESPONSE, MPI_COMM_WORLD); // send Fork response
                            printf("Table sent philosopher %d the forks\n", philosopher);
                            it = queue.erase(it); //Remove from wait list
                        }
                    }
                }
            }
        }
    }
    if (rank) {
        printf("Hello from philosopher %d \n", rank);
        int in_buffer[1];
        int out_buffer[1];
        MPI_Status stat;
        out_buffer[0];
        srand(time(NULL) + rank);

        //Philosopher main loop
        while (true) {
            printf("Philosopher %d is sleeping \n", rank);
            Sleep(rand() % 10); //Sleep
            printf("Philosopher %d is whaiting to eat \n", rank);

            MPI_Send(out_buffer, 1, MPI_INT, 0, FORK_REQUEST, MPI_COMM_WORLD); //Request forks
            MPI_Recv(in_buffer, 1, MPI_INT, 0, FORK_RESPONSE, MPI_COMM_WORLD, &stat); //Whait for response
            printf("Philosopher %d is eating \n", rank);
            Sleep(rand() % 10); //Eat
            printf("Philosopher %d is done eating \n", rank);
            MPI_Send(out_buffer, 1, MPI_INT, 0, FORK_RELEASE, MPI_COMM_WORLD); //Release forks
        }
    }
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Finalize();
    return 0;
}

【问题讨论】:

  • 如果你粘贴了这么多代码,你可能也粘贴了#include。此外,Sleep 未定义。你能否让你的代码开箱即用,这样 SO 用户就不必做完全不必要的工作?
  • 这在我的机器上运行正常。你是如何运行程序的?
  • 我使用“mpiexec -n 6 $(TargetName).exe”运行它并添加了包含

标签: c++ mpi


【解决方案1】:

尝试将MPI_REAL 替换为MPI_INT

编辑。 MPI_REAL 是为 Fortran 接口定义的;在我的机器中,它的值与MPI_FLOAT 不同。见the man pageMPI_SendMPI_Recv 可能会返回一个 MPI_ERR_TYPE 值,表示“无效的数据类型参数。”。因此,您的实现可能会检查发送和接收缓冲区的数据类型是否相同并发出错误信号。

您还有未初始化的发送/接收缓冲区,但这不是错误,因为它们的值未使用。

但是,我必须强调你的程序在我的机器上运行良好,所以你观察到的必须是依赖于实现的。对于这种未定义的行为,MPI_REAL 似乎是一个很好的候选者。

【讨论】:

  • 解释一下为什么会有帮助会很好;-)
  • @underscore_d 是的,是的,先生!
  • 我试过了,但没有帮助。也许你会因为 MPI 的版本而有错误?我有版本 10.1.12498.18,如果我没记错的话
  • 我使用 OpenMPI 4.0.5 (Linux)。 OMPI_MAJOR_VERSIONOMPI_MINOR_VERSIONOMPI_RELEASE_VERSION。恐怕我已经帮不上什么忙了。也许尝试通过大量使用std::cerr 来查明问题。
  • 您的 Windows / 软件安装也可能有问题。参见例如winosbite.com/fix-error-0x80000003 ;以及谷歌的具体错误代码。
猜你喜欢
  • 2016-03-04
  • 1970-01-01
  • 2019-02-07
  • 2010-10-26
  • 1970-01-01
  • 2010-10-11
  • 2013-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多