0

У меня есть Mac OS X Yosemite 10.10.1 (14B25).MPI on C, ошибка сегментации: 11

У меня есть некоторые проблемы с компиляцией кода. Вот он:

#include <stdio.h> 
#include <mpi.h> 

#define n 3 
#define repeats 1 

double abs(double item) 
{ 
    return (item > 0) ? item : -item; 
} 

int swap_raws (double **a, int p, int q) 
{ 
    if (p >= 0 && p < n && q >= 0 && q < n) 
    { 
     if (p == q) 
      return 0;  

     for (int i = 0; i < n; i++) 
     { 
      double temp = a[p][i]; 
      a[p][i] = a[q][i]; 
      a[q][i] = temp; 
     } 

     return 0; 
    } 
    else 
     return -1; 
} 

double f_column (int rank, int size, double *least) 
{ 
    double t1, t2, tbeg, tend, each_least = 1, least0; 
    int map[n]; 
    double **a = malloc (sizeof (*a) * n); 
    int i, j, k;  

    for (i = 0; i < n; i++) 
     a[i] = malloc (sizeof (*a[i]) * n);  

    if (rank == 0) 
     for (i = 0; i < n; i++) 
      for (j = 0; j < n; j++) 
       a[i][j] = 1.0/(i + j + 1); 

    MPI_Bcast (a, n * n, MPI_DOUBLE, 0, MPI_COMM_WORLD); 

    for (i = 0; i < n; i++) 
     map[i] = i % size; 

    MPI_Barrier (MPI_COMM_WORLD); 

    t1 = MPI_Wtime(); 

    for (k = 0; k < n - 1; k++) 
    { 
     double max = abs (a[k][k]); 
     int column = k; 

     for (j = k + 1; j < n; j++) 
     { 
      double absv = abs (a[k][j]); 

      if (absv > max) 
      { 
       max = absv; 
       column = j; 
      } 
     } 

     if (map[k] == rank && column != k && swap_raws (a, k, column)) 
     { 
      printf("ERROR SWAPPING %d and %d columns\n", k, column); 
      return -1; 
     } 

     MPI_Bcast (&a[k], n, MPI_DOUBLE, map[k], MPI_COMM_WORLD); 
     MPI_Bcast (&a[column], n, MPI_DOUBLE, map[k], MPI_COMM_WORLD); 

     if (map[k] == rank) 
      for (i = k + 1; i < n; i++) 
       a[k][i] /= a[k][k]; 

     MPI_Barrier (MPI_COMM_WORLD); 
     MPI_Bcast (&a[k][k+1], n - k - 1, MPI_DOUBLE, map[k], MPI_COMM_WORLD); 

     for (i = k + 1; i < n; i++) 
      if (map[i] == rank) 
       for (j = k + 1; j < n; j++) 
        a[j][i] -= a[j][k] * a[i][j]; 
    } 

    t2 = MPI_Wtime(); 

    for (i = 0; i < n; i++) 
     if (map[i] == rank) 
      for (j = 0; j < n; j++) 
      { 
       double absv = abs (a[i][j]); 

       if (each_least > absv) 
        each_least = absv; 

       //printf ("a[%d][%d] = %lg\n", j, i, a[i][j]); 
      } 

    MPI_Reduce (&each_least, &least0, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); 
    MPI_Reduce (&t1, &tbeg, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); 
    MPI_Reduce (&t2, &tend, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD); 

    for (i = 0; i < n; i++) 
     free (a[i]); 
    free (a); 

    if (rank == 0) 
    { 
     *least = least0; 
     return (tend - tbeg); 
    } 
} 

int main (int argc, char *argv[]) 
{ 
    int rank, size; 
    double min, max, aver, least; 

    if (n == 0) 
     return 0; 

    MPI_Init (&argc, &argv); 
    MPI_Comm_rank (MPI_COMM_WORLD, &rank); 
    MPI_Comm_size (MPI_COMM_WORLD, &size); 

    // It works! 
    //double try = f_column_non_parallel (rank, size, &least); 
    double try = f_column (rank, size, &least); 
    aver = max = min = try; 

    for (int i = 1; i < repeats; i++) 
    { 
     //double try = f_column_non_parallel (rank, size, &least); 
     double try = f_column (rank, size, &least); 

     if (try < min) 
      min = try; 
     else if (try > max) 
      max = try; 

     aver += try; 
    } 
    aver /= repeats; 

    MPI_Finalize(); 

    if (rank == 0) 
     printf("N: %d\nMIN: %f\nMAX: %f\nAVER: %f\nLEAST: %lg\n", size, min, max, aver, least); 

    return 0; 
} 

У меня есть матрица Гильберта. a (i) (j) = 1/(i + j + 1) для i, j от 0 до n

Этот код должен найти LU-разложение с использованием MPI, чтобы сделать это параллельно.

Первый процесс инициализирует массив, а затем передает его другим процессам.

Затем я нахожу максимум в необработанных и своп этих столбцах. Тогда я хотел бы транслировать эти данные в каждом процессе, то есть с помощью MPI_Barrier (MPI_COMM_WORLD);, но он говорит:

The error below Так что, я не знаю, что произошло, и как я могу решить эту проблему. Тот же вариант программы работает без использования процессов и непараллельной версии, но здесь не работает.

Если вы найдете решение, пример должен работать так (я сам его вычислял, вы тоже можете это проверить, но я могу признать, что это правда). Матрица (здесь J и я по вертикали и горизонтали соответственно, он работает в не такой удобный способ для людей, но вы должны принять его):

1 1/2 1/3 1 1/2 1/3  1 1/2 1/3  |1 1/2 1/3 | 
1/2 1/3 1/4 -> 1/2 1/12 1/12 -> 1/2 1/12 1  -> |1/2 1/12 1/12 | <- answer 
1/3 1/4 1/5 1/3 1/12 4/45 1/3 1/12 1/180 |1/3 1 1/180| 

Матрица источника так:

|1 0 0| |1 1/2 1/3 | |1 1/2 1/3| 
A = |1/2 1 0| * |0 1/12 1/12 | = |1/2 1/3 1/4| 
    |1/3 1 1| |0 0 1/180| |1/3 1/4 1/5| 

Можете ли вы помогите мне узнать, что сделана ошибка? Заранее спасибо :)

ответ

2

Ваша программа имеет ошибку в следующей части кода:

double **a = malloc (sizeof (*a) * n); 
[...snip...] 
MPI_Bcast (a, n * n, MPI_DOUBLE, 0, MPI_COMM_WORLD); 

Вы направляем ' n 'в "a", а не в массиве' n * n '. Поэтому, когда вы делаете MPI_Bcast «n * n» размера «a», вы запрашиваете MPI для передачи из местоположений памяти мусора, которые не выделены. Это приводит к сбою MPI.

Вы можете изменить «a» на просто «double *» вместо «double **» и выделить здесь «n * n» для исправления этой проблемы.

+0

Спасибо, очень полезный ответ :) – Beraliv

+0

@Beraliv, если это правильный ответ, продолжайте и отмечайте это как таковое, чтобы оба отдали честь Павану, и пусть остальные из нас знают, что этот вопрос сделан. –

+0

Это было бы как таковое, но это была не единственная проблема, поэтому я не могу отметить ее как полноценное решение, но мне это помогает, я сделал ошибку – Beraliv

0

Что меня больше всего огорчает, так это то, что f_column() должен возвращать двойной, но возвращаемое значение не определено, когда rank != 0.

Этот комментарий привлек мое внимание:

// It works! 
//double try = f_column_non_parallel (rank, size, &least); 
double try = f_column (rank, size, &least); 

Это говорит о том, что предыдущая версия f_column() работает, и что вы столкнулись с проблемами при попытке распараллелить его (я предполагаю, что это то, что вы делаете Теперь).

Как это могло бы привести к segfault, это не сразу кажется мне очевидным. Я ожидал бы исключение с плавающей запятой.

Пару других точек:

  • Я не слишком комфортно с кодом распределения памяти (я бы, вероятно, использовать calloc() вместо malloc() и sizeof() явных типов данных, и т.д. ...); это просто заводит меня, чтобы видеть такие вещи, как a[i] = malloc(sizeof (*a[i]) * n);, но это просто вопрос стиля, на самом деле.

  • У вас есть правильная проверка привязки (индексы свыше a всегда положительные и < n).

  • О, и вы переопределяете abs(), что, вероятно, не очень хорошая идея.

  • Попробуйте скомпилировать код в режиме отладки и запустите его с помощью gdb; также запустите его через valgrind, если вы можете, MacOS X должен поддерживаться к настоящему времени.

  • Вы, вероятно, следует более внимательно взглянуть на ваш компилятор ПРЕдуПРЕждЕНИя ;-)

+0

Прежде всего, он не был определен для непараллельной версии. Это означает, что процесс 0 является основным процессом и его единственным существенным для меня, чтобы вернуть значение. Во-вторых, хорошо, да, у меня есть проблемы с его параллелизмом. Кроме того, abs переопределяет, потому что это неверно с значениями, которые я хотел получить (и он был определен для int, если я не ошибаюсь). – Beraliv

+0

, но 'gdb' работает с параллельными программами, я компилирую эту программу не с помощью' gcc ... 'but' mpicc ..'? – Beraliv

Смежные вопросы