【问题标题】:MPI_Scatter() followed by malloc results in a segfaultMPI_Scatter() 后跟 malloc 导致段错误
【发布时间】:2017-04-04 17:48:35
【问题描述】:

我正在使用 MPI 和 C 进行编程,并且我正在使用根等级从文件中读取数据,然后将其分发到其余等级。我的 MPI_Scatter 工作正常,我打印出这些值以确保它们是正确的(并且它们是正确的)。我的问题是,在分配结构后,尝试从根级别以外的其他级别访问它们时出现段错误。

    pr_graph * graph = malloc(sizeof(*graph));
    ....

    MPI_Scatter(verticesCountArray, 1, MPI_INT, &(graph->nvtxs), 1, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
    MPI_Scatter(edgesCountArray, 1, MPI_INT, &(graph->nedges), 1, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);

    for(int rank = 0; rank<numProcesses; rank++){
      if (rank == myrank){
        fprintf(stderr, "%d %d \n",graph->nvtxs, graph->nedges );
        graph->xadj = malloc((graph->nvtxs + 1) * sizeof(*graph->xadj));
        graph->nbrs = malloc(graph->nedges * sizeof(*graph->nbrs));
        // graph->xadj[graph->nvtxs] = graph->nedges;

      }
      MPI_Barrier(MPI_COMM_WORLD);
    }

我的输出是:

    2 4 
    2 4 
    2 4 

这是正确的。但是当我取消注释注释行时,我得到:

    2 4 
    2 4 
    [phi01:07170] *** Process received signal ***
    [phi01:07170] Signal: Segmentation fault (11)
    [phi01:07170] Signal code:  (128)
    [phi01:07170] Failing at address: (nil)
    [phi01:07170] [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f5740503390]
    [phi01:07170] [ 1] ./pagerank[0x401188]
    [phi01:07170] [ 2] ./pagerank[0x400c73]
    [phi01:07170] [ 3] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f5740149830]
    [phi01:07170] [ 4] ./pagerank[0x400ce9]
    [phi01:07170] *** End of error message ***
    --------------------------------------------------------------------------
    mpirun noticed that process rank 1 with PID 7170 on node phi01 exited on signal 11 (Segmentation fault).

这意味着只有 rank 0 可以访问它分配的结构。谁能指出我为什么?谢谢!

编辑:

插入两个 recvbuffers 的任何值都不会出现段错误,并且会打印出正确的值。看来错误的根源在于使用 MPI_Scatter()。

    graph->nvtxs = 2;
    graph->nedges = 4;
    for(int rank = 0; rank<numProcesses; rank++){
      if (rank == myrank){
        fprintf(stderr, "%d %d \n",graph->nvtxs, graph->nedges );
        graph->xadj = malloc((graph->nvtxs + 1) * sizeof(*graph->xadj));
        graph->nbrs = malloc(graph->nedges * sizeof(*graph->nbrs));
        graph->xadj[graph->nvtxs] = graph->nedges;

      }
      MPI_Barrier(MPI_COMM_WORLD);
    }

【问题讨论】:

  • 欢迎来到 StackOverflow。请提供minimal reproducible example。否则无法帮你调试。如果您展示自己的努力来调试情况,这也将大有帮助。
  • 您好,谢谢! :) 这段代码是尽可能少的。原始源代码大约 500 行。代码中的“...”是我使用 0 级读取文件并填充我的两个数组(每个数组的大小为 numProcesses)的地方,因此我觉得包含它真的无关紧要。我已经在这个 bug 上工作了 6 个小时,终于设法将问题缩小到这 10 行代码。我不知道接下来要尝试什么,这就是我来到这里的原因:/ 我通过为我的两个数组插入任何值而不从文件中读取它们来重现此错误,但我仍然遇到同样的问题。

标签: c malloc mpi


【解决方案1】:

我找到了解决问题的方法。我会先发布它,然后尝试了解它的工作原理。

    pr_int * nvtxs = malloc(sizeof(pr_int));
    pr_int * nedges = malloc(sizeof(pr_int));

    MPI_Scatter(verticesCountArray, 1, MPI_INT, &(nvtxs), 1, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
    MPI_Scatter(edgesCountArray, 1, MPI_INT, &(nedges), 1, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);

    graph->nvtxs = nvtxs;
    graph->nedges = nedges;
    for(int rank = 0; rank<numProcesses; rank++){
      if (rank == myrank){
        fprintf(stderr, "%d %d \n",graph->nvtxs, graph->nedges );
        graph->xadj = malloc((graph->nvtxs + 1) * sizeof(*graph->xadj));
        graph->nbrs = malloc(graph->nedges * sizeof(*graph->nbrs));
        graph->xadj[graph->nvtxs] = graph->nedges;

      }
      MPI_Barrier(MPI_COMM_WORLD);
    }

我想我并没有使用实际的缓冲区(指针)来接收,只是使用常规变量。它们可能在调用 malloc 期间被转换为指针(地址值),这就是为什么结构的大小可能很疯狂的原因。但是,我仍然不确定为什么我能够打印这些值,甚至不知道 0 级是如何毫无问题地工作的。任何想法将不胜感激!谢谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-10
    相关资源
    最近更新 更多