2015-02-05 5 views
0

Может кто-нибудь сказать, что я делаю неправильно, из-за которого я получаю эту ошибку. Код:MPI_scatter: Invalid buffer pointer

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

void transpose(int ** p, int row, int col) 
{ 
    int ** tempVar; 
    tempVar = (int *)malloc(sizeof(int *)* row); 
    int i = 0; 
    for (; i < row; i++) 
    { 
     tempVar[i] = (int *)malloc(sizeof (int *)* col); 
     int j = 0; 
     while (j < col) 
     { 
      tempVar[i][j] = p[j][i]; 
      j++; 
     } 
    } 
    p = tempVar; 
} 
void main(int argc, char * argv[]) 
{ 
    int rank, size; 
    MPI_Init(argc, argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    int d[] = { 1000, 1000, 1000, 1000, 1000, 1000 }; 
    int vt[6] = { 1000, 1000, 1000, 1000, 1000, 1000 }; 
    int ** p; 
    p = (int *)malloc(sizeof(int *)* 6); 
    int i = 0; 
    int row = 6; 
    int col = 6; 
    while (i < 6) 
    { 
     p[i] = (int *)malloc(sizeof(int *)* 6); 
     /*int j = 0; 
     if (rank == 0) 
     { 
      while (j < 6) 
      { 
       scanf("%d", p[i][j]); 
       j++; 
      } 
     }*/ 
     i++;  
    } 
    p[0][0] = 0; p[0][1] =2 ; p[0][2] =3 ; p[0][3] =1 ; p[0][4] =1000 ; p[0][5] =1000 ; 
    p[1][0] = 2; p[1][1] = 0; p[1][2] = 1000; p[1][3] = 1000; p[1][4] = 5; p[1][5] = 1000; 
    p[2][0] = 3; p[2][1] = 1000; p[2][2] = 0; p[2][3] = 1000; p[2][4] = 1000; p[2][5] = 1; 

    p[3][0] = 1; p[3][1] = 1000; p[3][2] = 1000; p[3][3] = 0; p[3][4] = 4; p[3][5] = 3; 

    p[4][0] = 1000; p[4][1] = 5; p[4][2] = 1000; p[4][3] = 4; p[4][4] = 0; p[4][5] = 2; 

    p[5][0] = 1000; p[5][1] = 1000; p[5][2] = 1; p[5][3] = 3; p[5][4] = 2; p[5][5] = 0; 
    int smallest; 
    if (rank == 0) 
    { 
     //transpose(&p , row , col); 
     smallest = 0; 
     vt[smallest] = smallest; 
     //MPI_Bcast(); 
    } 
    int vt1, d1; 
    vt1 = d1 = 0; 

    int roww[6]; 
    MPI_Scatter(vt, 6, MPI_INT, vt1, 1, MPI_INT, 0, MPI_COMM_WORLD); 
    MPI_Scatter(d, 6, MPI_INT, d1, 1, MPI_INT, 0, MPI_COMM_WORLD); 
    MPI_Scatter(p, row *row, MPI_INT,roww, 6, MPI_INT, 0, MPI_COMM_WORLD); 
    i = 0; 
    while (i < (row*row)/size) 
    { 
     MPI_Bcast(smallest, 1, MPI_INT, 0, MPI_COMM_WORLD); 
     if (vt1 != rank) 
     { 
      if (roww[smallest] != 1000) 
      { 
       if (d1 > roww[smallest]) 
        d1 = roww[smallest]; 
      } 
     } 

     MPI_Gather(d1, 1, MPI_INT, d, row, MPI_INT, 0, MPI_COMM_WORLD); 
     if (rank == 0) 
     { 
      smallest = d[0]; 
      int k = 1; 
      int index = 0; 
      while (k < 6) 
      { 
       if (d[k] < smallest) 
       { 
        smallest = d[k]; 
        index = k; 
       } 
       k++; 
      } 
      vt[k] = index; 

     } 
     MPI_Scatter(vt, 6, MPI_INT, vt1, (row)/size, MPI_INT, 0, MPI_COMM_WORLD); 
     MPI_Scatter(d, 6, MPI_INT, d1, (row)/size, MPI_INT, 0, MPI_COMM_WORLD); 
i++; 

    } 
    MPI_Finalize(); 
} 

ошибка, что я получаю

Fatal Error: fatal error in MPI_Scatter: Invalid buffer pointer, error stack:
MPI_Scatter(760): MPI_Scatter(sbuf=0x0085f7ac , scount , MPI_INT , rbuf =0x0000000 , rcount =1, MPI_INT , root= 0 , MPI_COMM_WORLD) failed

+0

'p = tempVar' does * nothing * от имени вызывающего абонента. И это в результате утечки памяти, как сита. – WhozCraig

+0

, но здесь я просто назначаю адрес tempVar на p – Gardezi

+1

Нет, вы этого не сделали, вы назначаете адрес * в * 'tempVar'' p', .. который ничего не делает * от имени вызывающего абонента. 'p' является автоматической переменной для этой функции (знали ли вы это или нет). Это назначение ничего не возвращает на стороне вызывающего абонента. Если вы хотите, чтобы вызывающий абонент «получил» что-то, вам нужно объявить параметр как указатель на тип *, который вы хотите сохранить * отправить * адрес *, и назначить через * разыменование *: '* p = ... '. Поскольку написанный 'transpose' ничего не делает, кроме выделения некоторой памяти, вращения CPU, выполнения ничего не назначенного и утечки выделенной памяти. – WhozCraig

ответ

0

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

passing argument 2 of ‘MPI_Init’ from incompatible pointer type 

Look тщательно в прототипе функций: int* fun(int* b);, скорее всего, потерпит неудачу, если вы вызовете что-то вроде int d;fun(d);. Если функции требуется указатель на данные, fun(&d) может работать лучше. Эта проблема возникает много раз, так как вызываются функции MPI.

Подробнее: функция transpose(int ** p) пытается изменить p, выполнив p= tempVar. Как указано @WhozCraig, делая int **p;...;transpose(p,...), копия p в области функции transpose() изменяется, но не p. Следовательно, правильным прототипом этой функции является transpose(int ***p,...), и правильным способом ее можно назвать int** p;...;transpose(&p,...);

Что касается распределения памяти: вы нашли способ выделить 2D-массив! Но данные не смежны в памяти, так как строки выделяются по одному. Если вы планируете использовать функции MPI, такие как MPI_Scatter(), allocating a contiguous 2D array - это правильный путь (more).

Дополнительная рекомендация: позвоните по телефону free() в нужное время, чтобы освободить память и избежать утечек памяти. Do not cast the return of malloc()

Вот фрагмент кода, который должен хорошо компилироваться с mpicc main.c -o main -Wall. Опция -Wall включает все предупреждения. Кажется, что он работает нормально, хотя я не проверял правильность результата.

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

void transpose(int *** p, int row, int col) 
{ 
    int ** tempVar; 
    tempVar = malloc(sizeof(int *)* row); 
    if (tempVar==NULL){printf("malloc failed\n"); exit (1);} 
    tempVar[0] = malloc(sizeof (int)* col*row); 
    if (tempVar[0]==NULL){printf("malloc failed\n"); exit (1);} 
    int i = 0; 
    for (i=0; i < row; i++) 
    { 
     tempVar[i] = &tempVar[0][col*i]; 
     int j = 0; 
     while (j < col) 
     { 
      tempVar[i][j] = (*p)[j][i]; 
      j++; 
     } 
    } 
    free((*p)[0]); 
    free(*p); 
    *p = tempVar; 
} 
int main(int argc, char * argv[]) 
{ 
    int rank, size; 
    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    int d[] = { 1000, 1000, 1000, 1000, 1000, 1000 }; 
    int vt[6] = { 1000, 1000, 1000, 1000, 1000, 1000 }; 
    int ** p; 

    int i = 0; 
    int row = 6; 
    int col = 6; 
    p = malloc(sizeof(int *)* row); 
    if (p==NULL){printf("malloc failed\n"); exit (1);} 
    p[0] = malloc(sizeof(int)* row*col); 
    if (p[0]==NULL) {printf("malloc failed\n"); exit (1);} 
    while (i < row) 
    { 
     p[i] = &p[0][i*col]; 
     /*int j = 0; 
     if (rank == 0) 
     { 
      while (j < 6) 
      { 
       scanf("%d", p[i][j]); 
       j++; 
      } 
     }*/ 
     i++;  
    } 
    p[0][0] = 0; p[0][1] =2 ; p[0][2] =3 ; p[0][3] =1 ; p[0][4] =1000 ; p[0][5] =1000 ; 
    p[1][0] = 2; p[1][1] = 0; p[1][2] = 1000; p[1][3] = 1000; p[1][4] = 5; p[1][5] = 1000; 
    p[2][0] = 3; p[2][1] = 1000; p[2][2] = 0; p[2][3] = 1000; p[2][4] = 1000; p[2][5] = 1; 

    p[3][0] = 1; p[3][1] = 1000; p[3][2] = 1000; p[3][3] = 0; p[3][4] = 4; p[3][5] = 3; 

    p[4][0] = 1000; p[4][1] = 5; p[4][2] = 1000; p[4][3] = 4; p[4][4] = 0; p[4][5] = 2; 

    p[5][0] = 1000; p[5][1] = 1000; p[5][2] = 1; p[5][3] = 3; p[5][4] = 2; p[5][5] = 0; 
    int smallest; 
    if (rank == 0) 
    { 
     //transpose(&p , row , col); 
     smallest = 0; 
     vt[smallest] = smallest; 
     //MPI_Bcast(); 
    } 
    int vt1, d1; 
    vt1 = d1 = 0; 

    int roww[col]; 
    MPI_Scatter(vt, 1, MPI_INT, &vt1, 1, MPI_INT, 0, MPI_COMM_WORLD); 
    MPI_Scatter(d, 1, MPI_INT, &d1, 1, MPI_INT, 0, MPI_COMM_WORLD); 
    MPI_Scatter(&p[0][0], col, MPI_INT,roww, col, MPI_INT, 0, MPI_COMM_WORLD); 
    i = 0; 
    while (i < (row*row)/size) 
    { 
     MPI_Bcast(&smallest, 1, MPI_INT, 0, MPI_COMM_WORLD); 
     if (vt1 != rank) 
     { 
      if (roww[smallest] != 1000) 
      { 
       if (d1 > roww[smallest]) 
        d1 = roww[smallest]; 
      } 
     } 

     MPI_Gather(&d1, 1, MPI_INT, d, 1, MPI_INT, 0, MPI_COMM_WORLD); 
     if (rank == 0) 
     { 
      smallest = d[0]; 
      int k = 1; 
      int index = 0; 
      while (k < 6) 
      { 
       if (d[k] < smallest) 
       { 
        smallest = d[k]; 
        index = k; 
       } 
       k++; 
      } 
      vt[k] = index; 

     } 
     MPI_Scatter(vt, 1, MPI_INT, &vt1, 1, MPI_INT, 0, MPI_COMM_WORLD); 
     MPI_Scatter(d, 1, MPI_INT, &d1, 1, MPI_INT, 0, MPI_COMM_WORLD); 
     i++; 

    } 

    free(p[0]); 
    free(p); 
    MPI_Finalize(); 
    return 0; 
}