• MPI 函数说明 Dining philosophers哲学家进餐问题


    MPI函数说明

    • (1)并行初始化函数:int MPI_Init(int *argc,char ***argv)
      参数描述:argc为变量数目,argv为变量数组,两个参数均来自main函数的参数

    • (2)并行结束函数: int MPI_Finalize()

    • (3)获得当前进程标识函数:int MPI_Comm_rank(MPI_Comm comm,int *rank)
      参数描述:comm为该进程所在的通信域句柄,rank为调用这一函数返回的进程在通信域中的标识号

    • (4)获取通信域包含的进程总数函数:int MPI_Comm_size(MPI_Comm comm,int *size)
      参数描述:comm为通信域句柄,size为函数返回的通信域comm内包含的进程总数

    • (5)获得本进程的机器名函数:int MPI_Get_processor_name(char *name,int *resultlen)
      参数描述:name为返回的机器名字符串,resultlen为返回的机器名长度

    • (6)消息发送函数:
      int MPI_Send(void *buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm)
      参数描述:buf为发送缓冲区的起始地址,count为将发送的数据个数(以后面的数据类型进行计数),datatype为发送数据的数据类型,dest为目的进程标识号,tag为消息标识,comm为通信域
      MPI_Send()将发送缓冲区buf中得count个datatype数据类型的数据发送到标识号为dest的目的进程,本次发送的消息标识是tag

    • (7)消息接收受函数:
      int MPI_Recv(void *buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm,MPI_Status *status)
      参数描述:buf为接收缓冲区的起始地址,count为最多可接收的数据个数,datatype为接收数据的数据类型,source为接收数据的来源进程标识号,tag为消息标识,应与相应发送操作的标识相匹配,comm为本进程和发送进程所在的通信域,status为返回状态


    实例


    MPI_Send(
        void* data,
        int count,
        MPI_Datatype datatype,
        int destination,
        int tag,
        MPI_Comm communicator)
    
    MPI_Recv(
        void* data,
        int count,
        MPI_Datatype datatype,
        int source,
        int tag,
        MPI_Comm communicator,
        MPI_Status* status)
    • Although this might seem like a mouthful when reading all of the arguments, they become easier to remember since almost every MPI call uses similar syntax.
      • The first argument is the data buffer. The second and third arguments describe the count and type of elements that reside in the buffer. MPI_Send sends the exact count of elements, and MPI_Recv will receive at most the count of elements (more on this in the next lesson).
      • The fourth and fifth arguments specify the rank of the sending/receiving process and the tag of the message. The sixth argument specifies the communicator and the last argument (for MPI_Recv only) provides information about the received message.

    int token;
    if (world_rank != 0) {
        MPI_Recv(&token, 1, MPI_INT, world_rank - 1, 0,
                 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        printf("Process %d received token %d from process %d
    ",
               world_rank, token, world_rank - 1);
    } else {
        // Set the token's value if you are process 0
        token = -1;
    }
    MPI_Send(&token, 1, MPI_INT, (world_rank + 1) % world_size,
             0, MPI_COMM_WORLD);
    
    // Now process 0 can receive from the last process.
    if (world_rank == 0) {
        MPI_Recv(&token, 1, MPI_INT, world_size - 1, 0,
                 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        printf("Process %d received token %d from process %d
    ",
               world_rank, token, world_size - 1);
    }

    The ring program initializes a value from process zero, and the value is passed around every single process. The program terminates when process zero receives the value from the last process. As you can see from the program, extra care is taken to assure that it doesn’t deadlock. In other words, process zero makes sure that it has completed its first send before it tries to receive the value from the last process. All of the other processes simply call MPI_Recv (receiving from their neighboring lower process) and thenMPI_Send (sending the value to their neighboring higher process) to pass the value along the ring.MPI_Sendand MPI_Recv will block until the message has been transmitted. Because of this, the printfs should occur by the order in which the value is passed. Using five processes, the output should look like this.

    Process 1 received token -1 from process 0
    Process 2 received token -1 from process 1
    Process 3 received token -1 from process 2
    Process 4 received token -1 from process 3
    Process 0 received token -1 from process 4

    github_tutorials

    http://mpitutorial.com/tutorials/


    哲学家进餐问题, 无死锁

    Using MPI to solve the Dining philosophers problem

    /* 
      Compile:
        mpic++ philosophers.cpp -o philosophers
      Use:
        mpiexec -np 6 philosophers
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <list>
    #include "mpi.h"
    
    void philosopher( int );
    void table( int, int );
    #define FORK_REQUEST 1
    #define FORK_RESPONSE 2
    #define FORK_RELEASE 3
    #define DEBUG 1
    
    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 rand, 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){
        if(DEBUG) printf("Hello from philosopher %d 
    ", myrank);
        int in_buffer[1];
        int out_buffer[1];
        MPI_Status stat;
        out_buffer[0];
        srand (time(NULL) + myrank);
    
        //Philosopher main loop
        while(true){
    
            if(DEBUG) printf("Philosopher %d is sleeping 
    ", myrank);
            sleep(rand()%10); //Sleep
            if(DEBUG) printf("Philosopher %d is whaiting to eat 
    ", 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); //Whait for response
            if(DEBUG) printf("Philosopher %d is eating 
    ", myrank);
            sleep(rand()%10); //Eat
            if(DEBUG) printf("Philosopher %d is done eating 
    ", 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 
    ", myrank);
        int in_buffer[1];
        int out_buffer[1];
        int philosopher;
        MPI_Status stat;
    
        std::list<int> queue;
    
        bool fork[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
                if(DEBUG) printf("Table got philosopher %d fork request
    ", 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
                    if(DEBUG) printf("Table sent philosopher %d the forks
    ", 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;
                if(DEBUG) printf("Table got philosopher %d fork release
    ", 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%(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
                            if(DEBUG) printf("Table sent philosopher %d the forks
    ", philosopher);
                            it = queue.erase(it); //Remove from wait list
                        }
                    }
                }
            }
        }   
    }
  • 相关阅读:
    光学显微镜孔径光阑的正确使用
    win10c盘上的回收站已损坏
    Linux回顾【2】shell
    git 更新远端分支信息
    Linux回顾【3】文本编辑器 (vim/nano)
    C#面向抽象编程第二讲
    php7:给已编译安装版本增加一个编译参数(PHP 7.4.2)
    各种数值计算相关的问题
    告警运维中心|构建高效精准的告警协同处理体系
    CNCF 沙箱项目 OCM Placement 多集群调度指南
  • 原文地址:https://www.cnblogs.com/bishi/p/5699012.html
Copyright © 2020-2023  润新知