Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
па-пми / лр-2.docx
Скачиваний:
0
Добавлен:
10.06.2026
Размер:
280.3 Кб
Скачать

Приложение а Исходный код программы

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;

}

Соседние файлы в папке па-пми