MPI_Put 多个进程的段错误

问题描述 投票:0回答:1

我正在开发一个学习 MPI 单向通信的程序。在程序中,每个进程接收一个包含 N 个键、值对的本地数组。本地 N 可以变化,因此每个进程可以有不同大小的数组。程序应该对数组进行排序,以便进程 0 获取所有具有键 0 的值,进程 1 应该获取所有具有键 1 的值,依此类推,直到处理 P-1。

我的策略是首先让每个进程运行其本地数组,并在名为 local_counts 的本地数组中计算每个进程拥有多少个值。然后我使用 MPI_Allreduce 查找数组 global_counts 中的全局计数。然后我使用 MPI_Exscan 查找前缀和,以便我知道每个进程应该在另一个进程的 RMA 窗口中放置一个值的数组索引。

我创建具有适当大小的 window_buffer,创建 RMA 窗口,使用 MPI_fence 开始和结束一个纪元,并在纪元内我遍历本地数组并将值 i 放置在正确进程的 RMA 窗口的正确索引中。

当我用 1 个进程测试它时,效果很好。然而,它似乎不适用于多个进程,这有点违背了这一点。我在这里做错了什么,它不适用于超过 1 个进程?我会发布确切的输出,但我使用的自动评分器提供的反馈极其有限。它只告诉我,我已经正确地对值进行了排序,这可能意味着段错误或错误的答案。我知道它确实适用于 1 个进程。谢谢!

我的程序,sort.cpp:


#include <cmath>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <mpi.h>

#include "helper.h"
#include "sort.h"

void my_sort(int N, item *myItems, int *nOut, item **myResult)
{
    int rank, nprocs;
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int local_counts[nprocs] = {0};
    int global_counts[nprocs] = {0};
    int prefix_global_sum[nprocs] = {0};

    for (int i = 0; i < N; i++)
    {
        int key = myItems[i].key;
        local_counts[key]++;
    }

    fprintf(stdout, "Initial array: ");
    for (int i = 0; i < N; i++)
    {
        fprintf(stdout, "%d ", myItems[i].value);
    }
    fprintf(stdout, "\n");

    MPI_Allreduce(local_counts, global_counts, nprocs, MPI_INT, MPI_SUM, MPI_COMM_WORLD);

    MPI_Exscan(local_counts, prefix_global_sum, nprocs, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
    if (rank == 0)
    {
        for (int i = 0; i < nprocs; i++)
        {
            prefix_global_sum[i] = 0;
        }
    }

    *nOut = global_counts[rank]; 
    item *window_buffer[*nOut] = {0};
    MPI_Win window;
    *myResult = (item *)malloc(*nOut * sizeof(item));
    MPI_Win_create((*myResult), (MPI_Aint)*nOut * sizeof(item), sizeof(item), MPI_INFO_NULL,    MPI_COMM_WORLD, &window);

    MPI_Win_fence(0, window);

    for (int i = 0; i < N; i++)
    {
        val* value = &myItems[i].value;
        int target_rank = myItems[i].key;
        int target_offset = prefix_global_sum[target_rank];
        MPI_Put(value, sizeof(item), MPI_BYTE, target_rank, target_offset, sizeof(item), MPI_BYTE, window);
        prefix_global_sum[target_rank] += 1;
    }

    MPI_Win_fence(0, window);

    MPI_Win_free(&window);
}

排序.h:


#ifndef SORT_H
#define SORT_H

#include <cmath>
#include <algorithm>
#include <cstring>
#include <iostream> // for debugging, if you like
#include <mpi.h>
#include "helper.h"

void my_sort(int N, item *myItems, int *nOut, item **myResult);

#endif
c++ c mpi
1个回答
0
投票

我认为你的逻辑有问题。将数据放入

prefix_global_sum[target_rank]
后即可更新
target_rank
。但是,如果另一个进程将数据放在同一等级上怎么办?那么您的信息就不再正确了。

解决此问题的方法是让每个进程维护自己的

prefix_global_sum
值,当您想要将数据放入该进程时,您首先必须从该目标排名查询该值。

© www.soinside.com 2019 - 2024. All rights reserved.