Приложение а Исходный код программы
Main.c
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX_PAYLOAD 64
#define MIN_MSG_PER_PROC 1
#define MAX_MSG_PER_PROC 5
#define DATA_TAG 0
#define NOTIFY_TAG 1
#define TERMINATE_TAG 2
typedef struct{int dest;int src;int id;int visited_by_ctrl;int payload_len;char payload[MAX_PAYLOAD];} Message;
int main(int argc,char **argv){
MPI_Init(&argc,&argv);
int rank,size;
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
if(size<1){
if(rank==0)fprintf(stderr,"Неверное количество процессов.\n");
MPI_Finalize();
return 1;
}
int prev=(rank-1+size)%size;
int next=(rank+1)%size;
srand((unsigned)(time(NULL)+rank*97));
int delivered_count=0,deleted_count=0,sent_terminate=0;
int my_msg_count=MIN_MSG_PER_PROC+rand()%(MAX_MSG_PER_PROC-MIN_MSG_PER_PROC+1);
if(rank==0)printf("Запуск кольца: %d процессов. Каждый процесс генерирует от %d до %d сообщений.\n",size,MIN_MSG_PER_PROC,MAX_MSG_PER_PROC);
int total_messages=0;
MPI_Allreduce(&my_msg_count,&total_messages,1,MPI_INT,MPI_SUM,MPI_COMM_WORLD);
if(rank==0)printf("Всего сообщений в системе: %d\n",total_messages);
if(size==1){
for(int i=0;i<my_msg_count;++i){
Message msg;
msg.src=rank;
msg.id=i;
msg.visited_by_ctrl=0;
msg.dest=rand()%size;
snprintf(msg.payload,MAX_PAYLOAD,"Payload from %d id=%d",rank,i);
msg.payload_len=(int)strlen(msg.payload)+1;
printf("[rank %d] Локально доставлено сообщение id=%d payload='%s'\n",rank,msg.id,msg.payload);
delivered_count++;
}
if(rank==0)printf("Контролёр (единственный процесс): доставлено %d, удалено %d, всего=%d\n",delivered_count,deleted_count,total_messages);
MPI_Finalize();
return 0;
}
for(int i=0;i<my_msg_count;++i){
Message msg;
msg.src=rank;
msg.id=i;
msg.visited_by_ctrl=0;
msg.dest=rand()%size;
snprintf(msg.payload,MAX_PAYLOAD,"Payload from %d id=%d",rank,i);
msg.payload_len=(int)strlen(msg.payload)+1;
if(msg.dest==rank){
if(rank==0){
delivered_count++;
printf("[rank 0] Локальная доставка собственного сообщения id=%d. Всего доставлено (локально)=%d\n",msg.id,delivered_count);
}else{
int one=1;
MPI_Send(&one,1,MPI_INT,0,NOTIFY_TAG,MPI_COMM_WORLD);
printf("[rank %d] Локальная доставка собственного сообщения id=%d, уведомил контролёр\n",rank,msg.id);
}
continue;
}
MPI_Send(&msg,sizeof(Message),MPI_BYTE,next,DATA_TAG,MPI_COMM_WORLD);
printf("[rank %d] Отправил message id=%d (dest=%d) в %d\n",rank,msg.id,msg.dest,next);
}
int terminated=0;
while(!terminated){
MPI_Status status;
if(rank==0)MPI_Probe(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
else MPI_Probe(prev,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
if(status.MPI_TAG==DATA_TAG){
Message rmsg;
MPI_Recv(&rmsg,sizeof(Message),MPI_BYTE,status.MPI_SOURCE,DATA_TAG,MPI_COMM_WORLD,&status);
if(rmsg.dest==rank){
printf("[rank %d] Получено и доставлено message from %d id=%d'\n",rank,rmsg.src,rmsg.id);
if(rank==0){
delivered_count++;
if(!sent_terminate && delivered_count+deleted_count>=total_messages){
int term=1;
MPI_Send(&term,1,MPI_INT,next,TERMINATE_TAG,MPI_COMM_WORLD);
sent_terminate=1;
printf("[rank 0] Все сообщения обработаны (доставлено %d, удалено %d). Отправил TERMINATE.\n",delivered_count,deleted_count);
}
}else{
int one=1;
MPI_Send(&one,1,MPI_INT,0,NOTIFY_TAG,MPI_COMM_WORLD);
}
}else{
if(rank==0){
if(rmsg.visited_by_ctrl==0){
rmsg.visited_by_ctrl=1;
MPI_Send(&rmsg,sizeof(Message),MPI_BYTE,next,DATA_TAG,MPI_COMM_WORLD);
}else{
deleted_count++;
printf("[rank 0] Удалил недоставленное message from %d id=%d (dest=%d). Удалено всего: %d\n",rmsg.src,rmsg.id,rmsg.dest,deleted_count);
if(!sent_terminate && delivered_count+deleted_count>=total_messages){
int term=1;
MPI_Send(&term,1,MPI_INT,next,TERMINATE_TAG,MPI_COMM_WORLD);
sent_terminate=1;
printf("[rank 0] Все сообщения обработаны (доставлено %d, удалено %d). Отправил TERMINATE.\n",delivered_count,deleted_count);
}
}
}else{
MPI_Send(&rmsg,sizeof(Message),MPI_BYTE,next,DATA_TAG,MPI_COMM_WORLD);
}
}
}else if(status.MPI_TAG==NOTIFY_TAG){
int val;
MPI_Recv(&val,1,MPI_INT,status.MPI_SOURCE,NOTIFY_TAG,MPI_COMM_WORLD,&status);
if(rank==0){
delivered_count+=val;
printf("[rank 0] Получено уведомление о доставке от %d. Всего доставлено: %d\n",status.MPI_SOURCE,delivered_count);
if(!sent_terminate && delivered_count+deleted_count>=total_messages){
int term=1;
MPI_Send(&term,1,MPI_INT,next,TERMINATE_TAG,MPI_COMM_WORLD);
sent_terminate=1;
printf("[rank 0] Все сообщения обработаны (доставлено %d, удалено %d). Отправил TERMINATE.\n",delivered_count,deleted_count);
}
}
}else if(status.MPI_TAG==TERMINATE_TAG){
int term;
if(rank==0){
MPI_Recv(&term,1,MPI_INT,prev,TERMINATE_TAG,MPI_COMM_WORLD,&status);
printf("[rank 0] Получил возвращённый TERMINATE. Завершение.\n");
terminated=1;
}else{
MPI_Recv(&term,1,MPI_INT,prev,TERMINATE_TAG,MPI_COMM_WORLD,&status);
MPI_Send(&term,1,MPI_INT,next,TERMINATE_TAG,MPI_COMM_WORLD);
printf("[rank %d] Получил TERMINATE, переслал и завершаю.\n",rank);
terminated=1;
}
}else{ MPI_Recv(NULL,0,MPI_BYTE,status.MPI_SOURCE,status.MPI_TAG,MPI_COMM_WORLD,&status);
}
}
if(rank==0)printf("Контролёр: завершено. Доставлено: %d, Удалено: %d, Всего: %d\n",delivered_count,deleted_count,total_messages);
MPI_Finalize();
return 0;
}
