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; 
} 

나는 길버트 매트릭스를 가지고 있습니다. 0에서 n까지의 i, j에 대해 a (i) (j) = 1/(i + j + 1)

이 코드는 병렬 방식으로하기 위해 MPI를 사용하여 LU 분해를 찾아야합니다.

첫 번째 프로세스는 배열을 초기화 한 다음 다른 프로세스로 브로드 캐스트합니다.

그런 다음 원시에서 최대 값을 찾고 해당 열을 바꿉니다. 그럼 난 MPI_Barrier (MPI_COMM_WORLD);를 사용하여 모든 프로세스에 대한 데이터, 즉 방송 싶지만 그것은 말한다 :

The error below 그래서, 무슨 일이 있었 건지 모르겠어요 나는이 문제를 해결하는 방법에 대해 설명합니다. 프로세스와 비 병렬 버전을 사용하지 않고 프로그램의 동일한 변형이 실행되지만 여기서는 작동하지 않습니다.

솔루션을 찾으면 예제가 그와 같이 작동해야합니다 (직접 계산 했으므로 확인할 수도 있지만 사실이라고 인정할 수 있음). 매트릭스는 (여기서 j는 내가 수직 및 수평으로 각각, 그것은 사람들을 위해하지 이러한 편리한 방식으로 작동하지만 당신은 그것을해야) : 당신을

|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| 

수 : 그래서

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| 

소스 행렬 실수를 찾아 낼 수있게 도와 주시겠습니까? 미리 감사드립니다.

답변

2

여러분의 프로그램에 대해 자세히 살펴해야하는 코드의 다음 부분에 버그가 n '포인터가 아니라'n * n '배열의 포인터입니다. 그래서 "n * n"크기의 MPI_Bcast "a"를 할 때, 할당되지 않은 쓰레기 메모리 위치에서 MPI로 전송하도록 요청할 것입니다. 이로 인해 MPI가 분리됩니다.

"a"를 "double **"대신 간단히 "double *"로 변경하고이 문제를 해결하기 위해 'n * n'두 배를 할당 할 수 있습니다.

+0

고맙습니다. 정말 도움이되는 답변입니다. – Beraliv

+0

@Beraliv, 이것이 올바른 대답이라면, Pavan에게 공헌하고이 질문이 끝났음을 알게 해주십시오. –

+0

그것은 그럴 것이지만 유일한 해결책은 아니기 때문에 전체 솔루션으로 표시 할 수는 없지만 실수를하게하는 데 도움이됩니다. – Beraliv

0

가장 큰 슬픔은 f_column()입니다. f_column()은 double을 반환하지만, rank != 0 일 때 반환 값은 정의되지 않습니다.

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

그것은 f_column()의 이전 버전이 작동, 당신은 문제로 실행되었는지 (I 그 같은데요을 병렬화 할 때 것을 제안은 당신이 무슨 일을하는지입니다 :

이 코멘트는 내 관심을 끌었 지금).

어떻게 이것이 segfault로 이어질 수 있는지는 즉시 나에게 분명하지 않습니다. 부동 소수점 예외가 예상됩니다.

다른 점 몇 :

  • 나는 당신의 메모리 할당 코드와 너무 불편 해요 (I 아마 등, 명시 적 데이터 유형에 calloc() 대신 malloc()sizeof()를 사용하는 거라고 ...); a[i] = malloc(sizeof (*a[i]) * n);과 같은 것을보기 위해 나를 괴롭 히지만, 스타일의 문제 일뿐입니다.

  • 적절한 바운드 검사가있는 것 같습니다 (a 이상의 인덱스는 항상 양수이고 < n).

  • 오, 당신은 abs()을 재정의하고 있습니다. 이는 아마도 좋은 생각이 아닙니다.

  • 코드를 디버그 모드로 컴파일하고 gdb으로 실행하십시오. 가능한 경우 valgrind을 통해 실행하십시오. MacOS X는 지금 지원되어야합니다.

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

    당신이 할당됩니다

  • 당신은 아마 당신의 컴파일러 경고 ;-)

+0

우선, 비 병렬 버전에서도 정의되지 않았습니다. 즉, 프로세스 0은 주요 프로세스이고 그 값을 반환하기 위해서는 중요한 프로세스입니다. 둘째, 음, 그렇습니다. 병렬화에 문제가 있습니다. 또한 복근은 재정의하고 있습니다. 왜냐하면 복소수는 내가 얻고 자하는 값으로는 정확하지 않았기 때문입니다 (실수가 아니라면 int로 정의되었습니다). – Beraliv

+0

하지만'gdb'는 병렬 프로그램에서 작동합니다, 나는'gcc ... '가 아니라'mpicc ..'로 프로그램을 컴파일합니까? – Beraliv