【问题标题】:Segmentation fault of an MPI programMPI程序的分段错误
【发布时间】:2011-12-24 06:10:40
【问题描述】:

我正在用 C++ 编写一个使用 MPI 的程序。我的代码的简化版本是

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <mpi.h>
#define RNumber 3000000 //Number of loops to go

using namespace std;

class LObject {
        /*Something here*/
    public:
        void FillArray(long * RawT){
            /*Does something*/
            for (int i = 0; i < RNumber; i++){
                RawT[i] = i;
            }
        }
};

int main() {
    int     my_rank;
    int     comm_sz;
    MPI_Init(NULL, NULL);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);

    LObject System;

    long rawT[RNumber];
    long * Times = NULL;
    if (my_rank == 0) Times = (long*) malloc(comm_sz*RNumber*sizeof(long));

    System.FillArray(rawT);

    if (my_rank == 0) {
        MPI_Gather(rawT, RNumber, MPI_LONG, Times, RNumber,
                MPI_LONG, 0, MPI_COMM_WORLD);
    }
    else {
        MPI_Gather(rawT, RNumber, MPI_LONG, Times, RNumber,
                MPI_LONG, 0, MPI_COMM_WORLD);
    }

    MPI_Finalize();
    return 0;
};

程序可以正常编译,但在执行时会出现 Segmentation fault 错误。消息是

=================================================================================
=   BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
=   EXIT CODE: 11
=   CLEANING UP REMAINING PROCESSES
=   YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
=================================================================================
APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)

当我减少 RNumber 时,程序运行良好。也许有人可以解释究竟出了什么问题?我是否试图为数组分配太多空间?如果是这样的话,这个问题会不会通过将结果存储在文件而不是数组中来解决?

如果可能的话,请您就我做错的事情给出广泛的意见。

感谢您的时间和精力!

【问题讨论】:

    标签: c++ multithreading segmentation-fault mpi


    【解决方案1】:

    几个可能的问题:

    long rawT[RNumber];
    

    要放入堆栈的数组相当大。堆栈大小通常是有限制的(尤其是在多线程程序中),典型的大小是 1 或 2 兆字节。您最好在此处使用std::vector&lt;long&gt;

    Times = (long*) malloc(comm_sz*RNumber*sizeof(long));
    

    您应该检查内存分配是否成功。或者更好的是,在这里也使用std::vector&lt;long&gt;(这也将解决您的内存泄漏问题)。

    if (my_rank == 0) {
        // do stuff
    } else {
        // do exactly the same stuff
    }
    

    我猜else 块应该做一些不同的事情;特别是不涉及Times的东西,因为除非my_rank == 0,否则它是空的。

    更新:要使用向量而不是原始数组,只需将其初始化为您想要的大小,然后使用指向您将使用(指向)数组的第一个元素的指针:

    std::vector<long> rawT(RNumber);
    System.FillArray(&rawT[0]);
    
    std::vector<long> Times(comm_sz*RNumber);
    MPI_Gather(&rawT[0], RNumber, MPI_LONG, &Times[0], RNumber,
               MPI_LONG, 0, MPI_COMM_WORLD);
    

    请注意,如果您调整向量的大小,指针将会失效(尽管如果您只是将它用作数组的替换,则不需要这样做)。

    【讨论】:

    • 嗨!您提到的第三个问题是我之前使用不同功能进行通信时的试验遗留问题。自己不会注意到,所以非常感谢!关于 std::vector... 您能否提供有关此模板的手册或教程的链接?我找到了一些,但他们没有说明使用向量作为函数的参数,我自己也无法解决这个问题。感谢您的意见!
    • @J.K:查看我的更新。我不知道有什么好的在线教程;如果你对学习 C++ 很认真,good book 会很有帮助。
    • 尝试了您的线程中的调整,但它并没有改善程序。然而,矢量模板(事先对此一无所知)给了我关于如何调整程序以获得更好结果的想法。再次感谢!
    【解决方案2】:

    你可能想检查返回的内容

    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
    

    例如comm_sz==0 会导致这个问题。

    【讨论】:

      【解决方案3】:

      您没有检查来自malloc 的返回值。考虑到您试图分配超过 300 万个 long,malloc 失败的可能性很大。

      这可能不是导致您的问题的原因。

      【讨论】:

        猜你喜欢
        • 2014-05-07
        • 2017-06-25
        • 2019-06-26
        • 2014-08-22
        • 2023-04-11
        • 2011-12-29
        • 2012-01-24
        • 2012-05-11
        • 2015-02-18
        相关资源
        最近更新 更多