You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MPI点对点通信求进程最大值:多进程重复打印问题排查

MPI环形结构求最大值异常:多进程重复打印结果问题排查

问题描述

尝试通过MPI点对点通信,在环形拓扑的进程组中找出最大值(后续将扩展最小值功能)。0号进程向右侧1号进程发起数据传递,预期仅持有最大值的进程打印结果,但部分场景下会出现多个进程同时输出结果的情况。

问题代码

#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <mpi.h>

int main(int argc, char **argv)
{
    int rank, size, tag = 100;
    int rightrank, leftrank;
    int v, min, max, i, tmpmax, tmpmin;
    int *data;
    
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Status status;
    data = (int*) malloc(size * sizeof(int));
    
    rightrank = rank + 1;
    leftrank = rank - 1;
    
    if (rank == 0) {
        leftrank = size - 1;
    }
    if (rank == size - 1) {
        rightrank = 0;
    }
    
    for (i = 0; i < size; i++) {
        data[i] = rand() % 60;
    }
    v = data[rank];
    
//v=rank*10;
    printf("{rank %d , v = %d }\n", rank, v);
    
    if (rank == 0) {
        
        MPI_Send(&v, 1, MPI_INT, rightrank, tag, MPI_COMM_WORLD);
        
        MPI_Recv(&tmpmax, 1, MPI_INT, leftrank, tag, MPI_COMM_WORLD, &status);
    }
    else {
        
        MPI_Recv(&tmpmax, 1, MPI_INT, leftrank, tag, MPI_COMM_WORLD, &status);
        max = tmpmax;
        
        if (v > max) {
            max = v;
        }
        
        MPI_Send(&max, 1, MPI_INT, rightrank, tag, MPI_COMM_WORLD);
        
    }
    
    if (v == max) {
        printf("Me process of rank %d i have max value v = %d\n ", rank, v);
    }
    
    MPI_Finalize();
    return 0;
}

问题原因分析

  1. 0号进程max变量未初始化:
    非0号进程在接收数据后会初始化max并更新,但0号进程仅发送自身值、接收最终全局最大值到tmpmax,却从未将tmpmax赋值给max。此时0号进程的max是未定义的垃圾值,若该值恰好等于自身v,就会错误触发打印逻辑。

  2. 全局随机数种子一致导致重复值:
    所有进程调用rand()前未设置独立随机种子,默认种子相同,导致每个进程生成的data数组完全一致,多个进程的v值相同。这些进程的v都会等于传递后的全局最大值,从而同时打印结果。

修复方案

1. 补全0号进程的max变量初始化

在0号进程接收完tmpmax后,将其赋值给max,确保0号进程持有正确的全局最大值:

if (rank == 0) {
    MPI_Send(&v, 1, MPI_INT, rightrank, tag, MPI_COMM_WORLD);
    MPI_Recv(&tmpmax, 1, MPI_INT, leftrank, tag, MPI_COMM_WORLD, &status);
    max = tmpmax; // 新增:将接收的全局最大值赋值给max
}

2. 为每个进程设置独立随机数种子

在生成随机数前,用rank区分种子,避免所有进程生成相同的随机数据:

// 在data数组生成前添加
srand(time(NULL) + rank);

修复后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <mpi.h>

int main(int argc, char **argv)
{
    int rank, size, tag = 100;
    int rightrank, leftrank;
    int v, max, i, tmpmax;
    int *data;
    
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Status status;
    data = (int*) malloc(size * sizeof(int));
    
    rightrank = rank + 1;
    leftrank = rank - 1;
    
    if (rank == 0) {
        leftrank = size - 1;
    }
    if (rank == size - 1) {
        rightrank = 0;
    }
    
    // 设置独立随机种子
    srand(time(NULL) + rank);
    for (i = 0; i < size; i++) {
        data[i] = rand() % 60;
    }
    v = data[rank];
    
    printf("{rank %d , v = %d }\n", rank, v);
    
    if (rank == 0) {
        MPI_Send(&v, 1, MPI_INT, rightrank, tag, MPI_COMM_WORLD);
        MPI_Recv(&tmpmax, 1, MPI_INT, leftrank, tag, MPI_COMM_WORLD, &status);
        max = tmpmax; // 初始化0号进程的max
    }
    else {
        MPI_Recv(&tmpmax, 1, MPI_INT, leftrank, tag, MPI_COMM_WORLD, &status);
        max = tmpmax;
        
        if (v > max) {
            max = v;
        }
        
        MPI_Send(&max, 1, MPI_INT, rightrank, tag, MPI_COMM_WORLD);
    }
    
    if (v == max) {
        printf("进程%d持有最大值:%d\n", rank, v);
    }
    
    free(data); // 释放内存
    MPI_Finalize();
    return 0;
}

效果说明

修复后,全局最大值会正确在环形中传递并更新,每个进程都持有正确的全局最大值,仅真正拥有最大值的进程会打印结果;同时每个进程生成的随机值独立,避免因重复值导致的误打印。

内容的提问来源于stack exchange,提问作者MRS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 22:01:37