Разбросать матрицу - MPI - PullRequest
       18

Разбросать матрицу - MPI

2 голосов
/ 16 января 2011

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

вот моя ошибка при запуске

mpirun -np 2 ./a.out



 0.000000  1.000000  2.000000  3.000000  4.000000  5.000000  6.000000  7.000000  8.000000  9.000000
 10.000000  11.000000  12.000000  13.000000  14.000000  15.000000  16.000000  17.000000  18.000000  19.000000
 20.000000  21.000000  22.000000  23.000000  24.000000  25.000000  26.000000  27.000000  28.000000  29.000000
 30.000000  31.000000  32.000000  33.000000  34.000000  35.000000  36.000000  37.000000  38.000000  39.000000
 40.000000  41.000000  42.000000  43.000000  44.000000  45.000000  46.000000  47.000000  48.000000  49.000000
 50.000000  51.000000  52.000000  53.000000  54.000000  55.000000  56.000000  57.000000  58.000000  59.000000
 60.000000  61.000000  62.000000  63.000000  64.000000  65.000000  66.000000  67.000000  68.000000  69.000000
 70.000000  71.000000  72.000000  73.000000  74.000000  75.000000  76.000000  77.000000  78.000000  79.000000
 80.000000  81.000000  82.000000  83.000000  84.000000  85.000000  86.000000  87.000000  88.000000  89.000000
 90.000000  91.000000  92.000000  93.000000  94.000000  95.000000  96.000000  97.000000  98.000000  99.000000 

 rank = 1
 42.000000  43.000000  44.000000  45.000000  46.000000  47.000000  48.000000  49.000000  0.000000  0.000000
 52.000000  53.000000  54.000000  55.000000  56.000000  57.000000  58.000000  59.000000  0.000000  0.000000
 0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000
 0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000
 0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000 
[seismicmstm:07338] *** Process received signal *** [seismicmstm:07338] Signal:
 Segmentation fault (11)
 [seismicmstm:07338] Signal code: 
 (128) [seismicmstm:07338] Failing at
 address: (nil)
 -------------------------------------------------------------------------- mpirun noticed that process rank 1 with PID 7338 on node seismicmstm.cluster exited on signal 11 (Segmentation fault).
 --------------------------------------------------------------------------

Ответы [ 3 ]

6 голосов
/ 16 января 2011

Здесь происходит пара вещей.Хорошая новость заключается в том, что самые сложные вещи - создание типа данных mpi и базовая структура вызова MPI_Scatter - правильны.

Первая проблема заключается в том, что строка MPI_Scatter использует & (A [0] [0]) - но во всех случаях, кроме ранга ноль, вы не установили A, чтобы указывать на что-либо!Таким образом, вы разыменовываете случайный указатель дважды, и это ваш segfault.

Более тонкая проблема, как предполагает suszterpatt, заключается в том, что нет гарантии, что ваши строки выделенной памяти являются смежными, поэтому ваша операция разброса может не работатьдаже если вы исправите вышеуказанное.Вы пытаетесь отправить удвоения strip_size * A_col откуда-то из A в strip_A, но strip_A может не состоять из такого количества удваивающихся последовательных чисел - это может быть удвоение A_col, а затем некоторый отступ, затем удвоение A_col - или, действительно, различные строки могутбыть разбросанным по всей памяти.Три способа исправления, которые в порядке простоты (ИМХО): (a) делают данные непрерывными в памяти путем создания всего массива и последующего создания двумерных массивов C, указывающих на правильные места;(б) отправлять по одной строке за раз;или (c) создать тип данных MPI, который фактически отражает, как ваши данные отображаются (возможно, случайным образом) в памяти.

Подход, использующий (a), который, кажется, работает (для A_row, равномерно разделенного по размеру, в любом случае)) выглядит следующим образом:

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

int main(int argc, char** argv) {
  int rank, size;
  int strip_size, A_row, A_col;
  double **A, **strip_A, *Adata, *stripdata;
  MPI_Datatype strip;
  int i,j;

  MPI_Init(&argc,&argv) ;

  MPI_Comm_rank(MPI_COMM_WORLD,&rank) ;
  MPI_Comm_size(MPI_COMM_WORLD,&size) ;

      if(rank == 0) {
                    A_row = 10;
                    A_col = 10;
                    /* calculate the strip size */
                    strip_size = A_row / size;

                    /* genarate Matrix A */
                    Adata = (double *)malloc(sizeof(double)*A_row*A_col);
                    A = (double **)malloc(sizeof(double*) * A_row);
                    for(i = 0; i < A_row; i++) {
                            A[i] = &(Adata[i*A_col]);
                    }
                    int k = 0;
                    for(i = 0; i < A_row; i++) {
                            for(j = 0; j < A_col; j++) {
                                    A[i][j] = k;
                                    k++;
                            }
                    }
            }

            /* Broadcasting the row, column size of Matrix A as well as strip size and Matrix B*/
            MPI_Bcast(&A_row, 1, MPI_INT, 0, MPI_COMM_WORLD);
            MPI_Bcast(&A_col, 1, MPI_INT, 0, MPI_COMM_WORLD);
            MPI_Bcast(&strip_size, 1, MPI_INT, 0, MPI_COMM_WORLD);

            /* defining a datatype for sub-matrix */
            MPI_Type_vector(strip_size, A_col, A_col, MPI_DOUBLE, &strip);
            MPI_Type_commit(&strip);

            stripdata = (double *)malloc(sizeof(double)*strip_size*A_col);
            strip_A = (double **)malloc(sizeof(double*)*strip_size);
            for(i= 0; i< strip_size; i++) {
                    strip_A[i] = &(stripdata[i*A_col]);
            }

            MPI_Scatter(Adata, 1, strip, &(strip_A[0][0]), 1, strip, 0, MPI_COMM_WORLD);
            //MPI_Scatter(Adata, A_col*strip_size, MPI_DOUBLE, &(strip_A[0][0]), A_col*strip_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);

            for(i = 0; i < strip_size; i++) {
                    if(i == 0) {
                            printf("rank = %d\n", rank);
                    }
                    for(j = 0; j < A_col; j++) {
                            printf("%lf  ", strip_A[i][j]);
                    }
                    printf("\n");
            }

    MPI_Type_free(&strip);
    free(strip_A);
    free(stripdata);
    free(Adata);
    free(A);
    return 0;
}
1 голос
/ 16 января 2011

Я думаю, что в конечном итоге вы ошибаетесь, сохраняя свою матрицу в виде массива.Я думаю, вы обнаружите, что если вы будете хранить его в одном массиве (в мажорном порядке строк или столбцов, в зависимости от ваших предпочтений), все станет намного проще.

0 голосов
/ 16 июня 2018

Просто добавьте MPI_Finalize (); к вашей команде. ;) Смотрите код ниже и вывод. Вывод правильный, но он печатается неправильно из-за барьера. либо вы можете использовать MPI_Barrier () или MPI_Isend () и MPI_Irecv (). Наслаждайтесь

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

int main(int argc, char** argv) {
int rank, size;
int strip_size, A_row, A_col;
double **A, **strip_A, *Adata, *stripdata;
MPI_Datatype strip;
int i,j;

MPI_Init(&argc,&argv) ;

MPI_Comm_rank(MPI_COMM_WORLD,&rank) ;
MPI_Comm_size(MPI_COMM_WORLD,&size) ;

  if(rank == 0) {
                A_row = 10;
                A_col = 10;
                /* calculate the strip size */
                strip_size = A_row / size;

                /* genarate Matrix A */
                Adata = (double *)malloc(sizeof(double)*A_row*A_col);
                A = (double **)malloc(sizeof(double*) * A_row);
                for(i = 0; i < A_row; i++) {
                        A[i] = &(Adata[i*A_col]);
                }
                int k = 0;
                for(i = 0; i < A_row; i++) {
                        for(j = 0; j < A_col; j++) {
                                A[i][j] = k;
                                k++;
                        }
                }
        }

        /* Broadcasting the row, column size of Matrix A as well as strip size and Matrix B*/
        MPI_Bcast(&A_row, 1, MPI_INT, 0, MPI_COMM_WORLD);
        MPI_Bcast(&A_col, 1, MPI_INT, 0, MPI_COMM_WORLD);
        MPI_Bcast(&strip_size, 1, MPI_INT, 0, MPI_COMM_WORLD);

        /* defining a datatype for sub-matrix */
        MPI_Type_vector(strip_size, A_col, A_col, MPI_DOUBLE, &strip);
        MPI_Type_commit(&strip);

        stripdata = (double *)malloc(sizeof(double)*strip_size*A_col);
        strip_A = (double **)malloc(sizeof(double*)*strip_size);
        for(i= 0; i< strip_size; i++) {
                strip_A[i] = &(stripdata[i*A_col]);
        }

        MPI_Scatter(Adata, 1, strip, &(strip_A[0][0]), 1, strip, 0, MPI_COMM_WORLD);
        //MPI_Scatter(Adata, A_col*strip_size, MPI_DOUBLE, &(strip_A[0][0]), A_col*strip_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);

        for(i = 0; i < strip_size; i++) {
                if(i == 0) {
                        printf("rank = %d\n", rank);
                }
                for(j = 0; j < A_col; j++) {
                        printf("%lf  ", strip_A[i][j]);
                }
                printf("\n");
        }
if(rank == 0){
MPI_Type_free(&strip);
free(strip_A);
free(stripdata);
free(Adata);
free(A);}

 MPI_Finalize();

 return 0;
}

выход

rank = 0
0.000000  1.000000  2.000000  3.000000  4.000000  5.000000  6.000000  7.000000  8.000000  9.000000
rank = 2
 20.000000  21.000000  22.000000  23.000000  24.000000  25.000000  26.000000  27.000000  28.000000  29.000000  
rank = 6
60.000000  61.000000  62.000000  63.000000  64.000000  65.000000  66.000000  67.000000  68.000000  69.000000  
rank = 1
 10.000000  11.000000  12.000000  13.000000  14.000000  15.000000  16.000000  17.000000  18.000000  19.000000  
rank = 3
30.000000  31.000000  32.000000  33.000000  34.000000  35.000000  36.000000  37.000000  38.000000  39.000000  
rank = 5
50.000000  51.000000  52.000000  53.000000  54.000000  55.000000  56.000000  57.000000  58.000000  59.000000  
rank = 8
80.000000  81.000000  82.000000  83.000000  84.000000  85.000000  86.000000  87.000000  88.000000  89.000000  
rank = 7
70.000000  71.000000  72.000000  73.000000  74.000000  75.000000  76.000000  77.000000  78.000000  79.000000  
rank = 9
90.000000  91.000000  92.000000  93.000000  94.000000  95.000000  96.000000  97.000000  98.000000  99.000000  
rank = 4
40.000000  41.000000  42.000000  43.000000  44.000000  45.000000  46.000000  47.000000  48.000000  49.000000
...