【问题标题】:"Segmentation Fault" error when running MPI with more than one process使用多个进程运行 MPI 时出现“分段错误”错误
【发布时间】:2022-10-23 05:36:03
【问题描述】:

我正在编写一个与 MPI 并行生成单词的生成器。

当我使用如下单个进程运行生成器时,它会毫无问题地提供所需的输出。

    mpirun -np 1 ./bin/gen_data 2

输出是:

<<<==========GENERATION TEST START=========>>>
VT
BBZPTFTQ
WORD 0 : VT
WORD 1 : BBZPTFTQ
That took 0.000014 seconds
<<<===========GENERATION TEST END==========>>>

当我增加进程数时,例如,当它是两个时,我收到如下错误:

<<<==========GENERATION TEST START=========>>>
MTBVLUWXB
DVP
WORD 0 : DVP
[fati:17967] *** Process received signal ***
[fati:17967] Signal: Segmentation fault (11)
[fati:17967] Signal code:  (128)
[fati:17967] Failing at address: (nil)
[fati:17967] [ 0] /lib/x86_64-linux-gnu/libc.so.6(+0x43090)[0x7f978851f090]
[fati:17967] [ 1] ./bin/gen_data(+0xdf81)[0x5582c661bf81]
[fati:17967] [ 2] ./bin/gen_data(+0xe039)[0x5582c661c039]
[fati:17967] [ 3] ./bin/gen_data(+0xe3b1)[0x5582c661c3b1]
[fati:17967] [ 4] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) 
[0x7f9788500083]
[fati:17967] [ 5] ./bin/gen_data(+0xd78e)[0x5582c661b78e]
[fati:17967] *** End of error message ***
--------------------------------------------------------------------------
Primary job  terminated normally, but 1 process returned
a non-zero exit code. Per user-direction, the job has been aborted.
--------------------------------------------------------------------------
--------------------------------------------------------------------------
mpirun noticed that process rank 0 with PID 0 on node fati exited on signal 11 
(Segmentation fault).
--------------------------------------------------------------------------

这是我的代码:

生成器.cpp

#include "Generator.hpp"

int Generator::MAX_STR_LEN = 10;
int Generator::MIN_STR_LEN = 2;
int Generator::DATASET_SIZE = 50000;
char *Generator::LETTERS = (char *)malloc(Generator::LETTER_COUNT * sizeof (char));
int Generator::WORLD_SIZE = 1;
int *Generator::SCATTER_SEND_BUFFER = nullptr;
char **Generator::ALL_WORDS = nullptr;
int Generator::ELEMENTS_PER_PROC = DATASET_SIZE;


void Generator::validate(int argc, char **argv){

    if (Generator::WORLD_SIZE > 100)
        throw invalid_argument("WORLD_SIZE can be 100 at max");

    if (Generator::WORLD_SIZE < 1)
        throw invalid_argument("WORLD_SIZE can't be lowest from 1");
        
    if (argc < 2)
        throw invalid_argument("CLI arguments must have 2 arguments at least");

    Generator::DATASET_SIZE = atoi(argv[1]);

    if (strlen(argv[1]) > 7 || Generator::DATASET_SIZE > 1000000)
        throw invalid_argument("MPI_DATASET_SIZE can be 1M at max");

    if (Generator::DATASET_SIZE <= 0)
        throw invalid_argument("MPI_DATASET_SIZE can't be zero or negative");
    

    Generator::MAX_STR_LEN = 10;
    if (argc > 2)
       Generator::MAX_STR_LEN = atoi(argv[2]);

    if (Generator::MAX_STR_LEN > 100)
        throw invalid_argument("MAX_STR_LEN can be 100 at max");

    if (Generator::MAX_STR_LEN < 2)
        throw invalid_argument("MAX_STR_LEN can't be lowest from 2");

    Generator::MIN_STR_LEN = 2;
    if (argc > 3)
       Generator::MIN_STR_LEN = atoi(argv[3]);

    if (Generator::MIN_STR_LEN > 99)
        throw invalid_argument("MIN_STR_LEN can be 99 at max");

    if (Generator::MIN_STR_LEN < 1)
        throw invalid_argument("MIN_STR_LEN can't be lowest from 1");

    if (Generator::MIN_STR_LEN >= Generator::MAX_STR_LEN)
        throw invalid_argument("MIN_STR_LEN has to be lowest from MAX_STR_LEN");

    Generator::ELEMENTS_PER_PROC = Generator::DATASET_SIZE / Generator::WORLD_SIZE;

}

void Generator::createLetters(){
    for (int i = 0; i < Generator::LETTER_COUNT; i++)
        Generator::LETTERS[i] = 'A' + i;
}


Generator::Generator(int argc, char **argv){
    Generator::validate(argc, argv);
    Generator::createLetters();
}

Generator::Generator(){}

void Generator::Allocate2DArray(char ***arr, int row, int col){
    *arr = (char **)malloc(row * sizeof(char*));
    for (int i = 0; i < row; i++)
        (*arr)[i] = (char *)malloc(col * sizeof(char));
}

void Generator::CreateSendData(){
    Generator::SCATTER_SEND_BUFFER = (int *)malloc(Generator::WORLD_SIZE * sizeof(int));
    for (int i = 0; i < Generator::WORLD_SIZE; i++)
        SCATTER_SEND_BUFFER[i] = Generator::ELEMENTS_PER_PROC;
}

void Generator::CreateWord(char **word){
    int len = rand() % (Generator::MAX_STR_LEN - Generator::MIN_STR_LEN + 1) + Generator::MIN_STR_LEN;
    *word = (char *)malloc((Generator::MAX_STR_LEN) * sizeof(char));
    int i = 0;
    for (; i < len; i++)
    {
        int r = rand() % LETTER_COUNT;
        (*word)[i] = Generator::LETTERS[r];
    }
    if (len != MAX_STR_LEN)
        (*word)[i] = '\0';
}

void Generator::CreateWords(char **arr, int buff_size){
    for (int i = 0; i < buff_size; i++){
        char *word;
        Generator::CreateWord(&word);
        arr[i] = word;
    }
}

void Generator::WorkingTime(double start_time, double end_time){
    printf("That took %f seconds\n", end_time - start_time);
}

void Generator::WriteWord(char *word){
    for (int i = 0; i < Generator::MAX_STR_LEN; i++)
    {
        if (word[i] == '\0')
            break;
        cout << word[i];
    }
    
    cout << endl;
}

void Generator::WriteWords(){
    for (int i = 0; i < Generator::DATASET_SIZE; i++){
        cout << "WORD " << i << " : ";
        // assert(ALL_WORDS[i] != NULL);
        Generator::WriteWord(Generator::ALL_WORDS[i]);
    }
}

void Generator::WriteWords(char **arr, int buff_size){
    for (int i = 0; i < buff_size; i++)
        Generator::WriteWord(arr[i]);
}

测试生成.cpp

#include "Generator.hpp"
#include "Util.hpp"
#include <mpi.h>
#include <unistd.h>
int main(int argc, char **argv)
{

    Util::Clear();

    cout << "<<<==========GENERATION TEST START=========>>>" << endl;

    double start_time, end_time;

    MPI_Init(NULL, NULL);
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &Generator::WORLD_SIZE);

    Generator *generator = new Generator(argc, argv);

    start_time = MPI_Wtime();

    Generator::SCATTER_SEND_BUFFER = NULL;
    Generator::CreateSendData();
    assert(Generator::SCATTER_SEND_BUFFER != NULL);

    int scatter_recv_buffer;
    MPI_Barrier(MPI_COMM_WORLD);

    MPI_Scatter(Generator::SCATTER_SEND_BUFFER, 1, MPI_INT, &scatter_recv_buffer, 1, MPI_INT, 0, MPI_COMM_WORLD);
    srand((world_rank + 1) * time(0));

    char **words = NULL;
    Generator::Allocate2DArray(&words, scatter_recv_buffer, Generator::MAX_STR_LEN);
    Generator::CreateWords(words, scatter_recv_buffer);
    Generator::WriteWords(words, scatter_recv_buffer);

    if (world_rank == 0)
        Generator::Allocate2DArray(&Generator::ALL_WORDS, Generator::DATASET_SIZE, Generator::MAX_STR_LEN);

    MPI_Gather(words, scatter_recv_buffer * Generator::MAX_STR_LEN, MPI_CHAR, Generator::ALL_WORDS, scatter_recv_buffer * Generator::MAX_STR_LEN, MPI_CHAR, 0, MPI_COMM_WORLD);

    if (world_rank == 0)
    {
        end_time = MPI_Wtime();
        Generator::WriteWords();
        Generator::WorkingTime(start_time, end_time);
        cout << "<<<===========GENERATION TEST END==========>>>" << endl;
    }

    MPI_Finalize();
}

我可能无法使用 MPI_Gather 收集数据。

【问题讨论】:

  • 看起来像 C++ 看起来像 C。C 和 C++ 是两种不同的语言。如果你用 C++ 编译器编译它,那么它就是 C++,new 和其他不是 C
  • 这对Generator *generator = new Generator(argc, argv); 有什么好处?你没有将它用于任何事情,然后它就会泄漏。
  • 请始终使用std::vector。你应该基本上绝不使用new
  • 有指针算法,所以我添加了 C 标签,我用 C++ 编译我添加了 C++ 标签。谢天谢地,在您删除 C 标签之前,有人能够帮助我。
  • 不用担心,这只是一个学习 MPI 的项目,同时我正在刷新我的 C 知识。

标签: c++ char mpi


【解决方案1】:

您的基本问题是 Allocate2DArray 不创建二维数组:它创建一维数组的一维数组。因此,您不能将其用作 MPI 缓冲区。 MPI 缓冲区只能是(使用您的具体情况)char*

【讨论】:

  • 维克多,你真的很棒!我被困在这个问题上,我相信它正在创建一个二维数组,因为我已经对其进行了测试,但我不认为 MPI 缓冲区可能只是单个指针。无论如何,都不需要二维数组来将字符串保存在 char 数组中。非常感谢。
  • 你不是第一个犯这个错误的人,所以我很容易找到。
【解决方案2】:

正如@victor-eijkhout 所说,MPI 缓冲区只接受 char* 参数。

并且不需要二维数组来在 char 指针处保存字符串数组。

这是新的 Generator.cpp:

#include "Generator.hpp"

int Generator::MAX_STR_LEN = 10;
int Generator::MIN_STR_LEN = 2;
int Generator::DATASET_SIZE = 50000;
char *Generator::LETTERS = (char *)malloc(Generator::LETTER_COUNT * sizeof (char));
int Generator::WORLD_SIZE = 1;
int *Generator::SCATTER_SEND_BUFFER = nullptr;
char *Generator::ALL_WORDS = nullptr;
int Generator::ELEMENTS_PER_PROC = DATASET_SIZE;


void Generator::validate(int argc, char **argv){

    if (Generator::WORLD_SIZE > 100)
        throw invalid_argument("WORLD_SIZE can be 100 at max");

    if (Generator::WORLD_SIZE < 1)
        throw invalid_argument("WORLD_SIZE can't be lowest from 1");
        
    if (argc < 2)
        throw invalid_argument("CLI arguments must have 2 arguments at least");

    Generator::DATASET_SIZE = atoi(argv[1]);

    if (strlen(argv[1]) > 7 || Generator::DATASET_SIZE > 1000000)
        throw invalid_argument("MPI_DATASET_SIZE can be 1M at max");

    if (Generator::DATASET_SIZE <= 0)
        throw invalid_argument("MPI_DATASET_SIZE can't be zero or negative");
    

    Generator::MAX_STR_LEN = 10;
    if (argc > 2)
       Generator::MAX_STR_LEN = atoi(argv[2]);

    if (Generator::MAX_STR_LEN > 100)
        throw invalid_argument("MAX_STR_LEN can be 100 at max");

    if (Generator::MAX_STR_LEN < 2)
        throw invalid_argument("MAX_STR_LEN can't be lowest from 2");

    Generator::MIN_STR_LEN = 2;
    if (argc > 3)
       Generator::MIN_STR_LEN = atoi(argv[3]);

    if (Generator::MIN_STR_LEN > 99)
        throw invalid_argument("MIN_STR_LEN can be 99 at max");

    if (Generator::MIN_STR_LEN < 1)
        throw invalid_argument("MIN_STR_LEN can't be lowest from 1");

    if (Generator::MIN_STR_LEN >= Generator::MAX_STR_LEN)
        throw invalid_argument("MIN_STR_LEN has to be lowest from MAX_STR_LEN");

    Generator::ELEMENTS_PER_PROC = Generator::DATASET_SIZE / Generator::WORLD_SIZE;

}

void Generator::createLetters(){
    for (int i = 0; i < Generator::LETTER_COUNT; i++)
        Generator::LETTERS[i] = 'A' + i;
}


Generator::Generator(int argc, char **argv){
    Generator::validate(argc, argv);
    Generator::createLetters();
}

Generator::Generator(){}

// void Generator::Allocate2DArray(char ***arr, int row, int col){
//     *arr = (char **)malloc(row * sizeof(char*));
//     for (int i = 0; i < row; i++)
//         (*arr)[i] = (char *)malloc(col * sizeof(char));
// }

void Generator::CreateSendData(){
    Generator::SCATTER_SEND_BUFFER = (int *)malloc(Generator::WORLD_SIZE * sizeof(int));
    for (int i = 0; i < Generator::WORLD_SIZE; i++)
        SCATTER_SEND_BUFFER[i] = Generator::ELEMENTS_PER_PROC;
}

void Generator::CreateWord(char **word){
    int len = rand() % (Generator::MAX_STR_LEN - Generator::MIN_STR_LEN + 1) + Generator::MIN_STR_LEN;
    *word = (char *)malloc((Generator::MAX_STR_LEN) * sizeof(char));
    int i = 0;
    for (; i < len; i++)
    {
        int r = rand() % LETTER_COUNT;
        (*word)[i] = Generator::LETTERS[r];
    }
    if (len != MAX_STR_LEN)
        (*word)[i] = '
猜你喜欢
  • 2014-05-31
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 2012-01-01
  • 2015-05-01
  • 2021-07-18
  • 2013-11-30
  • 2013-09-13
相关资源
最近更新 更多