目前,我正在用C语言使用MPI库进行编程,我有以下代码片段,它们的行为非常奇怪。
这是而不是--一个最小的可重复示例,但是我认为代码片段存在一个明显的问题,甚至与mpi无关,可以很容易地解决这个问题,而无需重放。请让我知道是否有额外的代码需要,我很高兴地提供它!
void monitor_proposals(int people_per_gender) {
int satisfied_women = 0;
/* declarations independent of the one above (omitted) */
while (satisfied_women < people_per_gender) {
MPI_Recv(&buf, sizeof(buf), MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
sender = status.MPI_SOURCE;
index = sender/2;
printf("here\n");
printf("ppg=%d, sw=%d\n", people_per_gender, satisfied_women);
fflush(stdout);
if (women_atleast_one_proposal[index] == 0) {
women_atleast_one_proposal[index] = sender+1; /* logical id */
satisfied_women += 1;
printf("Monitor: First proposal to woman (%d)\n", sender+1);
printf("ppg=%d, sw=%d\n", people_per_gender, satisfied_women);
}
if (satisfied_women == people_per_gender) {
MPI_Send(&DONE, sizeof(DONE), MPI_INT, sender, sender, MPI_COMM_WORLD);
printf("this\n");
} else {
MPI_Send(&NOT_DONE, sizeof(NOT_DONE), MPI_INT, sender, sender, MPI_COMM_WORLD);
printf("that\n");
}
}
printf("outside\n");
}终端输出:
here
ppg=1, sw=16
Monitor: First proposal to woman (1)
ppg=1, sw=17
that当然,我的期望是satisfied_women被初始化为0,然后增加到1,因此当它迭代时会中断循环。我还将输出流刷新到stdout,这将显示是否存在不受控制的循环,但似乎没有。
预期产出:
here
ppg=1, sw=0
Monitor: First proposal to woman (1)
ppg=1, sw=1
this
outside我通过自制的方式使用mpich: stable 4.0.1。
编辑I解决了增量问题,这就是现在的代码,我(在几个地方将count参数更改为1,以便该部分现在起作用)。
有n个男人过程和n个女人过程。男人和女人都是一样的。男子通过派遣向妇女求婚,而妇女则等待求婚。如果一个女人比现在接受的男人得到更好的评价,那么前一个男人将不得不向另一个女人求婚。
在women's while-loop中,每迭代一次,就会有一个监视过程,如果它应该退出或不退出,它就会反馈给发送方。当女人离开while-loop时,她们通知了那个男人,最近他们接受了。
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef enum gender {
MAN,
WOMAN
} gender_t;
/* men use array of women and fill in each womens rating_t, and vice versa */
typedef struct rating {
gender_t gender;
int id;
int rating;
} rating_t;
/*******************************************************************************************
* HELPER FUNCTIONS ************************************************************************
*******************************************************************************************/
/* custom compare for qsort */
int compare(const void *r1, const void *r2) {
return ((rating_t*)r1)->rating > ((rating_t*)r2)->rating ? -1 : 1;
}
/* random shuffling of ratings */
void shuffle_ratings(rating_t *profiles, int size) {
int random_index, temp;
for (int max_index = size-1; max_index > 0; max_index--) {
random_index = rand() % (max_index+1);
/* swap values at indexes */
temp = profiles[max_index].rating;
profiles[max_index].rating = profiles[random_index].rating;
profiles[random_index].rating = temp;
}
}
/*******************************************************************************************
* PROCESSES *******************************************************************************
*******************************************************************************************/
/* keeps track of women who are with a man, eventually notifies them it's done */
void monitor_proposals(int people_per_gender) {
MPI_Status status;
const int DONE = 1;
const int NOT_DONE = 0;
int *women_atleast_one_proposal = (int*)calloc(people_per_gender, sizeof(int));
int satisfied_women = 0;
int sender, index;
int buf; /* not useful */
while (satisfied_women < people_per_gender) {
MPI_Recv(&buf, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
sender = status.MPI_SOURCE;
index = sender/2;
fflush(stdout);
if (women_atleast_one_proposal[index] == 0) {
women_atleast_one_proposal[index] = sender+1; /* logical id */
satisfied_women++;
printf("Monitor: First proposal to woman (%d)\n", sender+1);
printf("ppg=%d, sw=%d\n", people_per_gender, satisfied_women);
}
if (satisfied_women == people_per_gender) {
MPI_Send(&DONE, 1, MPI_INT, sender, sender, MPI_COMM_WORLD);
printf("this\n");
} else {
MPI_Send(&NOT_DONE, 1, MPI_INT, sender, sender, MPI_COMM_WORLD);
printf("that\n");
}
}
}
/* function for men, highest rating is proposed to first */
void propose(int id, rating_t *my_ratings) {
MPI_Status rec_status;
int proposals = 0;
int accepted = 0;
int propose_dest, propose_rating;
while (!accepted) {
propose_dest = my_ratings[proposals].id - 1;
propose_rating = my_ratings[proposals].rating;
printf("Man (%d): Proposed to woman (%d) who's rated %d\n", id, propose_dest+1, propose_rating);
fflush(stdout);
MPI_Send(&propose_rating, 1, MPI_INT, propose_dest, propose_dest, MPI_COMM_WORLD);
proposals++;
MPI_Recv(&accepted, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &rec_status);
}
printf("man %d accepted\n", id);
}
/* function for women, accepts first proposal but can replace */
void receive_proposals(int id, rating_t *my_ratings, int monitor_rank) {
MPI_Status status;
const int ACCEPT = 1;
const int REJECT = 0;
int DONT_CARE = 0;
int monitor_response;
int from_man;
int received_man_rank = -1;
int received_man_rating = -1;
int best_man_rank = -1;
int best_man_rating = -1;
while (1) {
MPI_Recv(&from_man, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
received_man_rank = status.MPI_SOURCE;
received_man_rating = my_ratings[received_man_rank/2].rating;
if (best_man_rank == -1) { /* first proposal received */
best_man_rank = received_man_rank;
best_man_rating = received_man_rating;
printf("Woman (%d): Accepted man (%d) #%d#\n", id, best_man_rank+1, best_man_rating);
} else if (received_man_rating > best_man_rating) { /* proposal is better rated than current accepted, notify replaced */
MPI_Send(&REJECT, 1, MPI_INT, best_man_rank, best_man_rank, MPI_COMM_WORLD);
printf("Woman (%d): Replaced man (%d) #%d# for man (%d) #%d#\n", id, best_man_rank+1, \
best_man_rating, received_man_rank+1, received_man_rating);
best_man_rank = received_man_rank;
best_man_rating = received_man_rating;
} else { /* notify denied man */
MPI_Send(&REJECT, 1, MPI_INT, received_man_rank, received_man_rank, MPI_COMM_WORLD);
printf("Woman (%d): Rejected proposing man (%d) #%d# due to best man (%d) #%d#\n", id, received_man_rank+1, \
received_man_rating, best_man_rank+1, best_man_rating);
}
MPI_Send(&DONT_CARE, 1, MPI_INT, monitor_rank, monitor_rank, MPI_COMM_WORLD);
MPI_Recv(&monitor_response, 1, MPI_INT, monitor_rank, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
if (monitor_response) {
printf("woman here\n");
break;
}
}
/* send ok to accepted man */
MPI_Send(&ACCEPT, 1, MPI_INT, best_man_rank, best_man_rank, MPI_COMM_WORLD);
printf("Woman (%d) + Man (%d) MARRIED\n", id, best_man_rank+1);
}
int main(int argc, char *argv[]) {
int pool_size, people_per_gender;
int rank, id, monitor_rank;
rating_t *my_ratings;
gender_t gender;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &pool_size);
if (pool_size % 2 != 1) {
if (rank == 0)
printf("Requirement: men == women and 1 extra process!\n");
MPI_Finalize();
exit(1);
}
people_per_gender = pool_size / 2; /* number of men/women */
id = rank + 1; /* logical id */
monitor_rank = pool_size - 1; /* collecting of proposals */
if (rank != monitor_rank) {
gender = (id % 2 == 0 ? MAN : WOMAN); /* odd id - woman, even id - man */
my_ratings = (rating_t*)malloc(people_per_gender * sizeof(rating_t)); /* rate half of pool, i.e. other gender */
/* create "profiles" of other gender */
for (int i = 0; i < people_per_gender; i++) {
my_ratings[i].gender = (gender == MAN ? WOMAN : MAN);
my_ratings[i].id = ( gender == MAN ? (2*i+1) : (2*i+2) );
my_ratings[i].rating = i+1;
}
/* randomize ratings of other gender */
srand(time(NULL) + id);
shuffle_ratings(my_ratings, people_per_gender);
qsort(my_ratings, people_per_gender, sizeof(rating_t), compare);
if (gender == WOMAN) printf("W(%d) ratings: ", id);
else if (gender == MAN) printf("M(%d) ratings: ", id);
for (int i = 0; i < people_per_gender; i++)
printf("| {id:%d, %d} | ", my_ratings[i].id, my_ratings[i].rating);
printf("\n");
}
MPI_Barrier(MPI_COMM_WORLD);
if (rank == monitor_rank) printf("\n");
fflush(stdout);
MPI_Barrier(MPI_COMM_WORLD);
/* call function based on process type */
if (rank == monitor_rank) {
monitor_proposals(people_per_gender);
} else {
if (gender == WOMAN)
receive_proposals(id, my_ratings, monitor_rank);
else if (gender == MAN)
propose(id, my_ratings);
}
MPI_Barrier(MPI_COMM_WORLD);
printf("ID (%d): Done\n", id);
MPI_Finalize();
return 0;
}发布于 2022-03-02 23:28:27
你没有给我们足够的密码。如何在以下文件中定义缓冲区:
MPI_Recv(&buf, sizeof(buf), MPI_INT,
int buf,这几乎是正确的,因为sizeof将给出4.int buf[20],然后sizeof将给出以字节为单位的大小,而不是在ints.buf = (int*)malloc(whatever)中,然后sizeof将为指针提供8个字节。换句话说,这是绝对错误的,但确切地说,我们无法分辨。
https://stackoverflow.com/questions/71330019
复制相似问题