Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.04.2017, 14:43   #1
Stacy McKritsky
 
Регистрация: 08.06.2015
Сообщений: 3
По умолчанию Обедающие философы MPI C++

Добрый день! Я нашла программу в интернете, решающую проблему обедающих философов на С++ с помощью MPI. Ниже прикрепляю код:
Код:
/*
Compile:
mpic++ philosophers.cpp -o philosophers
Use:
mpiexec -np 6 philosophers
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <list>
#include <Windows.h>
#include "mpi.h"
 
void philosopher(int);
void table(int, int);
#define FORK_REQUEST 1
#define FORK_RESPONSE 2
#define FORK_RELEASE 3
 
int main(int argc, char** argv) {
    int myrank, nprocs;
    //init MPI
    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
    
    //Depending on rank, Philosopher or Table
    if (myrank == 0)
    {
        table(myrank, nprocs);
    }
    else
    {
        philosopher(myrank);
    }
 
    MPI_Finalize();
    return 0;
}
 
/* Philosopher function - only philosopher processes run this */
void philosopher(int myrank) {
    printf("Hello from philosopher %d \n", myrank);
    int in_buffer[1];
    int out_buffer[1];
    MPI_Status stat;
    out_buffer[0];
    srand(time(NULL) + myrank);
 
    //Philosopher main loop
    while (true) {
        printf("Philosopher %d is sleeping \n", myrank);
        Sleep(rand() % 10); //Sleep
        printf("Philosopher %d is waiting to eat \n", myrank);
        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); //Wait for response
        printf("Philosopher %d is eating \n", myrank);
        Sleep(rand() % 10); //Eat
        printf("Philosopher %d is done eating \n", myrank);
        MPI_Send(out_buffer, 1, MPI_INT, 0, FORK_RELEASE, MPI_COMM_WORLD); //Release forks
    }
}
 
/* Table function - only table process run this */
void table(int myrank, int nprocs) {
    printf("Hello from table %d \n", myrank);
    int in_buffer[1];
    int out_buffer[1];
    int philosopher;
    MPI_Status stat;
 
    std::list<int> queue;
 
    bool *fork = new bool [nprocs-1];
    for (int i = 0; i < nprocs-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, &stat); // Recive next message
        philosopher = stat.MPI_SOURCE; //Read source of message
 
        if (stat.MPI_TAG == FORK_REQUEST) { //If Request for forks
            printf("Table got philosopher %d fork request\n", philosopher);
            if (fork[philosopher % (nprocs - 1)] == true && fork[philosopher - 1] == true) { //If both forks are free
                fork[philosopher % (nprocs - 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 (stat.MPI_TAG == FORK_RELEASE) { //If Release of forks
            fork[philosopher % (nprocs - 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 waiting for forks
                for (std::list<int>::iterator it = queue.begin(); it != queue.end(); it++) { //Go through whole list of waiting philosophers
                    philosopher = *it;
                    if (fork[philosopher % (nprocs - 1)] == true && fork[philosopher - 1] == true) { //If one of them can get both forks
                        fork[philosopher % (nprocs - 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, заходит только в функцию table и выводит из нее hello, тут все в порядке (так как процесс у нас всего один). А вот при запуске через консоль почему-то в функцию table не заходит вообще, и возвращает на нулевом процессе следующую ошибку: -1073740791: process 0 exited without calling finalize. Судя по логам, в таком случае оно в ветвь if где rank==0 вообще не заходит, как будто нулевого процесса и нет вообще (пробовала в if выводить что-нибудь и не вывелось). Но, что странно, если закомментировать выполнение одной из функций, либо table либо philosofer, программа хоть и не завершит свою работу, но если выполнение остановить то она выведет все что надо из обеих функций и нулевой процесс соответственно появляется. Подозреваю, что дело в бесконечных процессах while (true) в функциях, но понятия не имею что можно сделать. Помогите, пожалуйста, а то я уже несколько дней бьюсь над этой проблемой((
Прикрепляю скрин работы программы на 6 процессах (5 философов).
Изображения
Тип файла: jpg философы.jpg (88.5 Кб, 150 просмотров)

Последний раз редактировалось Stacy McKritsky; 14.04.2017 в 14:45. Причина: изменение метода оповещения
Stacy McKritsky вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обедающие философы в windows forms. Очень нужна помощь с переводом с Delphi в C#. SholpanB C# (си шарп) 1 03.12.2013 19:18
MPI Symple me Visual C++ 7 10.10.2012 14:51
Обедающие философы с использованием событий (events) RAZOR1703 Общие вопросы C/C++ 0 23.10.2011 18:32
Семафоры, философы. kir_rik Помощь студентам 0 12.04.2010 14:17
Философы, блин... ds.Dante Свободное общение 10 18.11.2009 18:14