【问题标题】:MPI debugging Segmentation faultMPI调试分段错误
【发布时间】:2015-02-18 23:19:19
【问题描述】:

我正在尝试使用奇偶转置对随机数数组进行排序,但在运行代码时我不断收到分段错误:

[islb:48966] *** Process received signal ***
[islb:48966] Signal: Segmentation fault (11)
[islb:48966] Signal code: Address not mapped (1)
[islb:48966] Failing at address: 0x28
[islb:48966] [ 0] /lib64/libpthread.so.0(+0xf810)[0x7fc3da4cb810]
[islb:48966] [ 1] /lib64/libc.so.6(memcpy+0xa3)[0x7fc3da1c7cf3]
[islb:48966] [ 2] /usr/local/lib/libopen-pal.so.6(opal_convertor_unpack+0x10b)[0x7fc3d9c372db]
[islb:48966] [ 3] /usr/local/lib/openmpi/mca_pml_ob1.so(mca_pml_ob1_recv_request_progress_match+0x138)[0x7fc3d58507a8]
[islb:48966] [ 4] /usr/local/lib/openmpi/mca_pml_ob1.so(mca_pml_ob1_recv_req_start+0x1b1)[0x7fc3d5850d11]
[islb:48966] [ 5] /usr/local/lib/openmpi/mca_pml_ob1.so(mca_pml_ob1_recv+0x139)[0x7fc3d5849489]
[islb:48966] [ 6] /usr/local/lib/libmpi.so.1(MPI_Recv+0xc0)[0x7fc3da742f40]
[islb:48966] [ 7] oddEven[0x40115a]
[islb:48966] [ 8] /lib64/libc.so.6(__libc_start_main+0xe6)[0x7fc3da161c36]
[islb:48966] [ 9] oddEven[0x400c19]
[islb:48966] *** End of error message ***
--------------------------------------------------------------------------
mpirun noticed that process rank 1 with PID 48966 on node islb exited on signal 11 (Segmentation fault).
--------------------------------------------------------------------------

程序分配数组,当涉及到将其分散到进程中时,错误似乎发生,因为在分散调用之后直接打印语句仅打印进程 0,然后打印错误消息。

这是我的代码:

#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <time.h>
#include <string.h>
#include "mpi.h"

const int MAX = 10000;
int myid, numprocs;
int i, n, j, k, arrayChunk, minindex;
int A, B;
int temp;

int swap(int *x, int *y) {
  temp = *x;
  *x = *y;
  *y = temp;
  return 0;
}

int main(int argc, char **argv) {
  int* arr = NULL;
  int* value = NULL;
  MPI_Status status;
  //int arr[] = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};

  srand(time(0));
  time_t t1, t2;

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &myid);
  MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

  if (myid == 0) {
    printf("Enter the number of elements you would like in the array \n");
    scanf("%d", &n);

    arrayChunk = n/numprocs;
    //printf("cpus: %d, #s per cpu: %d\n", numprocs, arrayChunk);

    //Allocate memory for the array
    arr = malloc(n * sizeof(int));
    value = malloc(n * sizeof(int));

    // Generate an array of size n random numbers and prints them
    printf("Elements in the array: ");
    for (i = 0; i < n; i++) {
      arr[i] = (rand() % 100) + 1;
      printf("%d ", arr[i]);
    }
    printf("\n");
    time(&t1);
  }

  if ((n % numprocs) != 0) {
    if (myid == 0)
      printf("Number of Elements are not divisible by numprocs \n");
    MPI_Finalize();
    return(0);
  }

  // Broadcast the size of each chunk
  MPI_Bcast(&arrayChunk, 1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Scatter(&arr, arrayChunk, MPI_INT, &value, arrayChunk, MPI_INT, 0, MPI_COMM_WORLD);
  printf("Processor %d receives %d\n", myid, value[0]);

  for (i = 0; i < numprocs; i++) {
    if (i % 2 == 0) {
      if (myid%2 == 0) {
        MPI_Send(&value[0], arrayChunk, MPI_INT, myid + 1, 0, MPI_COMM_WORLD);
        MPI_Recv(&value[arrayChunk], arrayChunk, MPI_INT, myid + 1, 0, MPI_COMM_WORLD, &status);

        for (j = 0; j < (arrayChunk * 2 - 1); j++) {
          minindex = j;
          for (k = j + 1; k < arrayChunk * 2; k++) {
            if (value[k] < value[minindex]) {
              minindex = k;
            }
          }
          if (minindex > j) {
            swap(&value[j], &value[minindex]);
          }
        }
        //printf("myid %d i: %d, %d\n", myid, i, value[0]);
      } else {
        MPI_Recv(&value[arrayChunk], arrayChunk, MPI_INT, myid - 1, 0, MPI_COMM_WORLD, &status);
        MPI_Send(&value[0], arrayChunk, MPI_INT, myid - 1, 0, MPI_COMM_WORLD);

        for (j = 0; j < (arrayChunk * 2 - 1); j++) {
          minindex = j;
          for (k = j + 1; k < arrayChunk * 2; k++) {
            if (value[k] < value[minindex]) {
              minindex = k;
            }
          }
          if (minindex > j) {
            swap(&value[j], &value[minindex]);
          }
        }

        for (j = 0; j < arrayChunk; j++) {
         swap(&value[j], &value[j + arrayChunk]);
        }
        //printf("myid %d i: %d, %d\n", myid, i, value[0]);
      }
    } else {
      if ((myid%2 == 1) && (myid != (numprocs-1))) {
        MPI_Send(&value[0], arrayChunk, MPI_INT, myid + 1, 0, MPI_COMM_WORLD);
        MPI_Recv(&value[arrayChunk], arrayChunk, MPI_INT, myid + 1, 0, MPI_COMM_WORLD, &status);

        for (j = 0; j < (arrayChunk * 2 - 1); j++) {
          minindex = j;
          for (k = j + 1; k < arrayChunk * 2; k++) {
            if (value[k] < value[minindex]) {
              minindex = k;
            }
          }
          if (minindex > j) {
            swap(&value[j], &value[minindex]);
          }
        }
        //printf("myid %d i: %d, %d\n", myid, i, value[0]);
      } else if (myid != 0 && myid != (numprocs-1)) {
        MPI_Recv(&value[arrayChunk], arrayChunk, MPI_INT, myid - 1, 0, MPI_COMM_WORLD, &status);
        MPI_Send(&value[0], 1, MPI_INT, myid - 1, 0, MPI_COMM_WORLD);

        for (j = 0; j < (arrayChunk * 2 - 1); j++) {
          minindex = j;
          for (k = j + 1; k < arrayChunk * 2; k++) {
            if (value[k] < value[minindex]) {
              minindex = k;
            }
          }
          if (minindex > j) {
            swap(&value[j], &value[minindex]);
          }
        }

        for (j = 0; j < arrayChunk; j++) {
          swap(&value[j], &value[j + arrayChunk]);
        }
        //printf("myid %d i: %d, %d\n", myid, i, value[0]);
      }
    }
  }

  MPI_Gather(&value[0], arrayChunk, MPI_INT, &arr[0], arrayChunk, MPI_INT, 0, MPI_COMM_WORLD);

  if (myid == 0) {
    time(&t2);
    printf("Sorted array: ");
    for (i = 0; i < n; i++) {
      printf("%d ", arr[i]);
    }
    printf("\n");
    printf("Time in sec. %f\n", difftime(t2, t1));
  }

  // Free allocated memory
  if (arr != NULL) {
    free(arr);
    arr = NULL;

    free(value);
    value = NULL;
  }
  MPI_Finalize();
  return 0;
}

我对 C 不是很熟悉,很可能是我错误地使用了 malloc 和/或地址和指针,因此它可能很简单。

抱歉代码量太大,但我认为最好提供所有代码以进行适当的调试。

【问题讨论】:

  • 如果您提供重现问题的最小示例,您更有可能获得帮助。
  • 这一行,在 swap() 函数内部:'temp = *x;'正在使用全局变量 'temp' 使用局部/自动变量会更好:'int temp = *x;'注意:3 异或操作将是 1) 更快 2) 不需要任何堆栈空间用于 'temp'
  • 这一行:arrayChunk = n/numprocs;正在执行整数除法。如果 numprocs 大于用户输入的 'n' 则结果将始终为 0
  • free() 函数检查 NULL 指针,因此无需用户代码也执行检查
  • 在这一行:'printf("Enter the number of elements you want in the array \n");'该代码没有为用户提供足够的信息。用户需要知道 numprocs 的值,并且 n 必须是 numprocs 的倍数

标签: c debugging mpi


【解决方案1】:

我将使用调试信息(很可能是-g 编译标志)构建程序,尝试获取 coredump 并尝试使用gdb 调试器来定位错误。 Corefile 是在进程崩溃时创建的,它保存崩溃时的进程内存映像。

如果程序崩溃后没有创建核心转储文件,您需要弄清楚如何在您的系统上启用它。您可以创建简单的错误程序(例如带有a=x/0; 或类似错误)并玩一下。 Coredump 可能被称为corePID.core(PID - 崩溃进程的数量)或类似名称。有时使用ulimit 设置核心文件大小 tu 无限 就足够了。还要检查 Linux 上的 kernel.core_* sysctl。

一旦有了 corecump,就可以将它与 gdb 或类似的调试器 (ddd) 一起使用:

gdb executable_file core

【讨论】:

    【解决方案2】:

    问题出在您的MPI_Scatter 命令中。您尝试将信息分散并存储在value 中,但是如果您查看该代码上方,则只有排名0 为value 分配了任何内存。当任何和所有其他等级尝试将数据存储到value 时,您将遇到分段错误(确实如此)。相反,从if 块内删除value = malloc(...); 行,并将其放在MPI_Bcast 之后作为value = malloc(arrayChunk * sizeof(int));。我没有查看其余代码以查看其他地方是否也存在任何问题,但这可能是最初的 seg-fault 的原因。

    【讨论】:

      猜你喜欢
      • 2012-05-11
      • 2014-05-07
      • 2017-06-25
      • 2019-06-26
      • 2012-01-24
      • 1970-01-01
      • 2011-12-24
      • 2016-03-22
      • 2017-11-10
      相关资源
      最近更新 更多