无根生成树异步Leader选举MPI实现:多胜者问题排查
异步无根生成树Leader选举算法的平局问题(MPI实现)
我正在基于MPI实现一款无根生成树异步Leader选举算法,这是大学分布式卫星-地面站通信系统项目的一部分。经过多次迭代实现,始终无法解决选举出现多个候选胜者时的平局问题。

选举流程实现函数
该函数由协调进程(rank 10)通过START_LELECT_GS事件触发,在5个地面站进程(GS 0、1、2、3、4)上分别执行:
void perform_gs_leader_election(int coordinator_rank, int rank, MPI_Comm comm) { MPI_Status status; int is_leader = 0; int received_count = 0; int neighbor_received_from[num_of_neighbors]; printf("Process %d: Starting leader election\n", rank); // 判断是否为叶子节点 const int is_leaf = (num_of_neighbors == 1); printf("Process %d: Is leaf? %d\n", rank, is_leaf); // 仅叶子节点发送初始<ELECT>消息 if (is_leaf) { MPI_Send(&rank, 1, MPI_INT, neighbor_gs[0], ELECT, comm); printf("Leaf Process %d: Sent ELECT to %d\n", rank, neighbor_gs[0]); } // 接收并处理来自邻居的消息 while (1) { int sender_rank; MPI_Recv(&sender_rank, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, comm, &status); printf("Process %d: Received message from %d with tag %d\n", rank, status.MPI_SOURCE, status.MPI_TAG); if (status.MPI_TAG == ELECT) { received_count++; neighbor_received_from[status.MPI_SOURCE] = 1; printf("Process %d: Received ELECT from %d\n", rank, status.MPI_SOURCE); // 若除一个邻居外其他都已发送ELECT,先探测是否有消息再发送给剩余邻居 if (received_count == num_of_neighbors - 1) { int flag; MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, comm, &flag, &status); if (flag && status.MPI_TAG == TERMINATE_LELECT_GS) { printf("Process %d: Received TERMINATE_LELECT_GS from %d\n", rank, status.MPI_SOURCE); if (status.MPI_SOURCE > rank) { printf("Process %d: Surrendering leadership to process %d\n", rank, status.MPI_SOURCE); MPI_Send(&rank, 1, MPI_INT, status.MPI_SOURCE, GS_LEADER, comm); is_leader = 0; } else { printf("Process %d: Declaring leadership over process %d\n", rank, status.MPI_SOURCE); is_leader = 1; } // 向除发送方外的所有邻居转发终止消息 for (int i = 0; i < num_of_neighbors; i++) { if (neighbor_gs[i] != status.MPI_SOURCE) { MPI_Send(&rank, 1, MPI_INT, neighbor_gs[i], TERMINATE_LELECT_GS, comm); printf("Process %d: Forwarded TERMINATE_LELECT_GS to %d\n", rank, neighbor_gs[i]); } } break; } if (!flag) { // 给未发送ELECT的剩余邻居发送消息 for (int i = 0; i < num_of_neighbors; i++) { if (!neighbor_received_from[neighbor_gs[i]]) { MPI_Send(&rank, 1, MPI_INT, neighbor_gs[i], ELECT, comm); printf("Process %d: Sent ELECT to remaining neighbor %d\n", rank, neighbor_gs[i]); break; } } } } // 若所有邻居都已发送ELECT,成为leader候选 if (received_count == num_of_neighbors) { printf("Process %d: Candidate for leader\n", rank); is_leader = 1; // 向所有邻居发送终止消息 for (int i = 0; i < num_of_neighbors; i++) { MPI_Send(&rank, 1, MPI_INT, neighbor_gs[i], TERMINATE_LELECT_GS, comm); printf("Process %d: Sent TERMINATE_LELECT_GS to %d\n", rank, neighbor_gs[i]); } break; } } else if (status.MPI_TAG == TERMINATE_LELECT_GS) { printf("Process %d: Received TERMINATE_LELECT_GS from %d\n", rank, status.MPI_SOURCE); for (int i = 0; i < num_of_neighbors; i++) { if (neighbor_gs[i] != status.MPI_SOURCE) { MPI_Send(&rank, 1, MPI_INT, neighbor_gs[i], TERMINATE_LELECT_GS, comm); printf("Process %d: Forwarded TERMINATE_LELECT_GS to %d\n", rank, neighbor_gs[i]); } } break; } else if (status.MPI_TAG == GS_LEADER) { printf("Process %d: Declared leader due to GS_LEADER message\n", rank); is_leader = 1; for (int i = 0; i < num_of_neighbors; i++) { if (neighbor_gs[i] != status.MPI_SOURCE) { MPI_Send(&rank, 1, MPI_INT, neighbor_gs[i], TERMINATE_LELECT_GS, comm); printf("Process %d: Sent TERMINATE_LELECT_GS to %d\n", rank, neighbor_gs[i]); } } break; } } MPI_Barrier(comm); printf("Process %d: Terminated\n", rank); if (is_leader) { printf("Process %d: Sending LELECT_GS_DONE to coordinator\n", rank); MPI_Send(&rank, 1, MPI_INT, coordinator_rank, LELECT_GS_DONE, MPI_COMM_WORLD); } }
问题输出示例
parsing START_LELECT_GS event Process 0: Starting leader election Process 0: Is leaf? 0 Process 1: Starting leader election Process 1: Is leaf? 0 Process 4: Starting leader election Process 4: Is leaf? 1 Leaf Process 4: Sent ELECT to 0 Process 2: Starting leader election Process 3: Starting leader election Process 3: Is leaf? 1 Leaf Process 3: Sent ELECT to 1 Process 2: Is leaf? 1 Leaf Process 2: Sent ELECT to 1 Process 0: Received message from 4 with tag 22 Process 0: Received ELECT from 4 Process 0: Sent ELECT to remaining neighbor 1 Process 1: Received message from 3 with tag 22 Process 1: Received ELECT from 3 Process 1: Received message from 2 with tag 22 Process 1: Received ELECT from 2 Process 1: Sent ELECT to remaining neighbor 0 Process 1: Received message from 0 with tag 22 Process 1: Received ELECT from 0 Process 1: Candidate for leader Process 1: Sent TERMINATE_LELECT_GS to 3 Process 1: Sent TERMINATE_LELECT_GS to 0 Process 1: Sent TERMINATE_LELECT_GS to 2 Process 0: Received message from 1 with tag 22 Process 0: Received ELECT from 1 Process 0: Candidate for leader Process 0: Sent TERMINATE_LELECT_GS to 1 Process 0: Sent TERMINATE_LELECT_GS to 4 Process 4: Received message from 0 with tag 24 Process 4: Received TERMINATE_LELECT_GS from 0 Process 3: Received message from 1 with tag 24 Process 3: Received TERMINATE_LELECT_GS from 1 Process 2: Received message from 1 with tag 24 Process 2: Received TERMINATE_LELECT_GS from 1 Process 0: Terminated Process 0: Sending LELECT_GS_DONE to coordinator Process 3: Terminated Process 4: Terminated Process 1: Terminated Process 1: Sending LELECT_GS_DONE to coordinator process 10 waiting at barrier Process 2: Terminated
问题说明
选举出现了两个候选胜者,尽管我尝试通过探测TERMINATE_LELECT_GS消息来提前打破平局,但该方案并未生效,无法找到问题原因,寻求帮助。
内容的提问来源于stack exchange,提问作者Stelios Papamichail
相关产品推荐
相关产品推荐

