【问题标题】:Why my C++ parallel program gives MPI fatal error in MPI_Gather?为什么我的 C++ 并行程序在 MPI_Gather 中出现 MPI 致命错误?
【发布时间】:2021-05-20 14:42:21
【问题描述】:

我的排序程序适用于数组中的偶数个元素,但会出错

" MPI_Gather 中的致命错误:消息被截断,错误堆栈: MPI_Gather(sbuf=0x00A2A700, scount=4, MPI_INT, rbuf=0x00A302C8, rcount=4, MPI_INT, root=0, MPI_COMM_WORLD) 来自 rank 1 的消息失败 并且标签 -1342177184 被截断;收到 28 个字节,但缓冲区大小为 16 "

表示数组中的奇数个元素。 问题始于代码if ((world_rank == 1) && (n % world_size != 0))。我尝试了一切,但没有奏效。我怎样才能解决这个问题?提前致谢!

void merge(int*, int*, int, int, int);
void mergeSort(int*, int*, int, int);

int main(int argc, char** argv) {

    


    int world_rank;
    int world_size;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

    int n = atoi(argv[1]);
    int* original_array{ new int[n] {} };
    //int original_array[]=new int[n];

    int c;
    srand(time(NULL));

    if (world_rank == 0) {
        printf("This is the unsorted array: ");
        for (c = 0; c < n; c++) {

        original_array[c] = rand() % n;
        printf("%d ", original_array[c]);

        }
        printf("\n");
        printf("\n");
    }
    
    
    int size = n / world_size;
    int* sub_array=NULL;
    int* tmp_array = NULL;
    int* sorted = NULL;

    if (world_rank == 0) {

        sorted = { new int[n] {} };

    }


    if ((world_rank == 1) && (n % world_size != 0)) {
        int r = n % world_size;
        int size2 = size + r;
        sub_array = { new int[size2] {} };
        MPI_Scatter(original_array, size2, MPI_INT, sub_array, size2, MPI_INT, 0, MPI_COMM_WORLD);
        tmp_array = { new int[size2] {} };
        mergeSort(sub_array, tmp_array, 0, (size2 - 1));
        MPI_Gather(sub_array, size2, MPI_INT, sorted, size2, MPI_INT, 0, MPI_COMM_WORLD);
    }
    else {
        sub_array = { new int[size] {} };
        MPI_Scatter(original_array, size, MPI_INT, sub_array, size, MPI_INT, 0, MPI_COMM_WORLD);
        tmp_array = { new int[size] {} };
        mergeSort(sub_array, tmp_array, 0, (size - 1));
        MPI_Gather(sub_array, size, MPI_INT, sorted, size, MPI_INT, 0, MPI_COMM_WORLD);
    }

    

    

    
    if (world_rank == 0) {

        printf("Array state before final mergeSort call: ");
        for (c = 0; c < n; c++) {

            printf("%d ", sorted[c]);

        }
        
        printf("\n");

        int* other_array{ new int[n] {} };
        mergeSort(sorted, other_array, 0, (n - 1));

        printf("This is the sorted array: ");
        for (c = 0; c < n; c++) {

            printf("%d ", sorted[c]);

        }

        printf("\n");
        printf("\n");

        delete[] sorted;
        delete[] other_array;

    }

    delete[] original_array;
    delete[] sub_array;
    delete[] tmp_array;

    /********** Finalize MPI **********/
    MPI_Finalize();

}

【问题讨论】:

    标签: c++ performance parallel-processing mpi hpc


    【解决方案1】:

    TL;DR:对于偶数个元素,进程调用 MPI_ScatterMPI_Gather 并使用相同的 count,但它们不会调用奇数。

    我的排序程序适用于数组中的偶数个元素

    数组大小是偶数时,所有进程都会执行else的部分:

       if ((world_rank == 1) && (n % world_size != 0)) {
            int r = n % world_size;
            int size2 = size + r;
            sub_array = { new int[size2] {} };
            MPI_Scatter(original_array, size2, MPI_INT, sub_array, size2, MPI_INT, 0, MPI_COMM_WORLD);
            tmp_array = { new int[size2] {} };
            mergeSort(sub_array, tmp_array, 0, (size2 - 1));
            MPI_Gather(sub_array, size2, MPI_INT, sorted, size2, MPI_INT, 0, MPI_COMM_WORLD);
        }
        else {
            sub_array = { new int[size] {} };
            MPI_Scatter(original_array, size, MPI_INT, sub_array, size, MPI_INT, 0, MPI_COMM_WORLD);
            tmp_array = { new int[size] {} };
            mergeSort(sub_array, tmp_array, 0, (size - 1));
            MPI_Gather(sub_array, size, MPI_INT, sorted, size, MPI_INT, 0, MPI_COMM_WORLD);
        }
    

    但给出错误“ MPI_Gather 中的致命错误:消息被截断,错误 堆栈:MPI_Gather(sbuf=0x00A2A700,scount=4,MPI_INT,rbuf=0x00A302C8, rcount=4, MPI_INT, root=0, MPI_COMM_WORLD) 来自 rank 1 的消息失败 并且标签 -1342177184 被截断;收到 28 个字节,但缓冲区大小为 16 " 表示数组中的奇数个元素。

    但是,当数组的大小为奇数时,进程 1 执行上述if and elseif 部分,而其他进程执行else 部分。因此,某些进程将使用不同的count 调用例程MPI_GatherMPI_Scatter。这些例程应该被所有进程以相同的方式调用。

    要修复您的代码,您可以对其进行更改,以便所有进程使用相同的 count MPI_ScatterMPI_Gather 例程调用。

    一般来说,当输入的大小没有除以进程数时,您将面临与您相同的问题。为了解决这个问题,可以将 dummy 值添加到数组中,以便大小均匀地除以进程数。或者可以使用MPI_Gatherv

    从一个组中的所有进程聚集到指定位置

    MPI_Scatterv

    将缓冲区分散到通信器中的所有进程中

    来自source 可以阅读:

    MPI_Gatherv 和 MPI_Scatterv 是可变消息大小的版本 MPI_Gather 和 MPI_Scatter。 MPI_Gatherv 扩展了 MPI_Gather 允许来自每个进程的不同数量的数据,并 允许在收集的数据放在哪里有一定的灵活性 根进程。它通过将 count 参数从 单个整数到整数数组并提供新参数 displs (数组) 。 MPI_Scatterv 以类似的方式扩展 MPI_Scatter。 有关使用这些例程的更多信息将在 本模块后面的应用示例。

    【讨论】:

      猜你喜欢
      • 2012-01-08
      • 2020-06-14
      • 2013-11-27
      • 1970-01-01
      • 2023-04-10
      • 2021-04-08
      • 2014-09-24
      • 1970-01-01
      • 2023-02-08
      相关资源
      最近更新 更多