C语言 多进程MPI_Put seg故障

j0pj023g  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(97)

我正在做一个学习MPI单边通信的程序。在程序中,每个进程接收一个具有N个键、值对的本地数组。局部N可以变化,因此每个进程可以有不同大小的数组。程序应该对数组进行排序,使得进程0得到所有键为0的值,进程1得到所有键为1的值,以此类推,直到进程P-1。
我的策略是首先让每个进程运行它们的本地数组,并计算它们在一个名为local_counts的本地数组中为每个进程拥有多少值。然后我使用MPI_Allreduce来查找数组global_counts中的全局计数。然后,我使用MPI_Exscan来查找前缀和,这样我就知道每个进程应该在另一个进程的RMA窗口中放置数组的哪些索引。
我创建了一个大小合适的window_buffer,创建了一个RMA窗口,使用MPI_fence来开始和结束一个epoch,在epoch内部,我遍历了本地数组,并将值i放在正确进程的RMA窗口的正确索引中。
当我用1个进程测试它时,它工作得很好。然而,它似乎不能与多个进程一起工作,这有点违背了这一点。我在这里做错了什么,它不适用于多个进程?我会发布确切的输出,但我使用的是一个自动评分器,它提供的反馈非常有限。它只告诉我,我在正确排序的值,这可能意味着一个segfault或错误的答案。我知道它确实适用于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);
}

sort.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
iugsix8n

iugsix8n1#

我认为你的逻辑有错误。在将数据放到target_rank上之后,您可以更新prefix_global_sum[target_rank]。但是,如果另一个进程将数据放在同一个级别上呢?你的信息就不再正确了。
解决这个问题的方法是让每个进程维护自己的prefix_global_sum值,当你想把数据放在那个进程上时,你首先必须从那个目标排名中查询那个值。

相关问题