2017-01-30 19 views
0

私は単純に2つの行列を作成しています:1つの行列は次元arows x nsameであり、もう1つは次元nsame x bcolsです。結果は、arows x bcolsの次元の配列です。これは、BLASを使用して実装することはかなり簡単で、OpenMPIのと下のマスタースレーブモデルを使用する場合は、次のコードは、意図したとおりに動作しているように見えます: `サイズが大きくなると行列計算エラーが表示されます

#include <iostream> 
#include <stdio.h> 
#include <iostream> 
#include <cmath> 
#include <mpi.h> 
#include <gsl/gsl_blas.h> 
using namespace std;` 

int main(int argc, char** argv){ 
    int noprocs, nid; 
    MPI_Status status; 
    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &nid); 
    MPI_Comm_size(MPI_COMM_WORLD, &noprocs); 
    int master = 0; 

    const int nsame = 500; //must be same if matrices multiplied together = acols = brows 
    const int arows = 500; 
    const int bcols = 527; //works for 500 x 500 x 527 and 6000 x 100 x 36 
    int rowsent; 
    double buff[nsame]; 
    double b[nsame*bcols]; 
    double c[arows][bcols]; 
    double CC[1*bcols]; //here ncols corresponds to numbers of rows for matrix b 
    for (int i = 0; i < bcols; i++){ 
       CC[i] = 0.; 
    }; 
    // Master part 
    if (nid == master) { 

     double a [arows][nsame]; //creating identity matrix of dimensions arows x nsame (it is I if arows = nsame) 
     for (int i = 0; i < arows; i++){ 
      for (int j = 0; j < nsame; j++){ 
       if (i == j) 
        a[i][j] = 1.; 
       else 
        a[i][j] = 0.; 
      } 
     } 
     double b[nsame*bcols];//here ncols corresponds to numbers of rows for matrix b 
      for (int i = 0; i < (nsame*bcols); i++){ 
       b[i] = (10.*i + 3.)/(3.*i - 2.) ; 
      }; 
     MPI_Bcast(b,nsame*bcols, MPI_DOUBLE_PRECISION, master, MPI_COMM_WORLD); 
     rowsent=0; 
     for (int i=1; i < (noprocs); i++) { 
      // Note A is a 2D array so A[rowsent]=&A[rowsent][0] 
      MPI_Send(a[rowsent], nsame, MPI_DOUBLE_PRECISION,i,rowsent+1,MPI_COMM_WORLD); 
      rowsent++; 
     } 

     for (int i=0; i<arows; i++) { 
      MPI_Recv(CC, bcols, MPI_DOUBLE_PRECISION, MPI_ANY_SOURCE, MPI_ANY_TAG, 
        MPI_COMM_WORLD, &status); 
      int sender = status.MPI_SOURCE; 
      int anstype = status.MPI_TAG;   //row number+1 
      int IND_I = 0; 
      while (IND_I < bcols){ 
       c[anstype - 1][IND_I] = CC[IND_I]; 
       IND_I++; 
      } 
      if (rowsent < arows) { 
       MPI_Send(a[rowsent], nsame,MPI_DOUBLE_PRECISION,sender,rowsent+1,MPI_COMM_WORLD); 
       rowsent++; 
      } 
      else {  // tell sender no more work to do via a 0 TAG 
       MPI_Send(MPI_BOTTOM,0,MPI_DOUBLE_PRECISION,sender,0,MPI_COMM_WORLD); 
      } 
     } 
    } 

    // Slave part 
    else { 
     MPI_Bcast(b,nsame*bcols, MPI_DOUBLE_PRECISION, master, MPI_COMM_WORLD); 
     MPI_Recv(buff,nsame,MPI_DOUBLE_PRECISION,master,MPI_ANY_TAG,MPI_COMM_WORLD,&status); 
     while(status.MPI_TAG != 0) { 
      int crow = status.MPI_TAG; 
      gsl_matrix_view AAAA = gsl_matrix_view_array(buff, 1, nsame); 
      gsl_matrix_view BBBB = gsl_matrix_view_array(b, nsame, bcols); 
      gsl_matrix_view CCCC = gsl_matrix_view_array(CC, 1, bcols); 

      /* Compute C = A B */ 
      gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, &AAAA.matrix, &BBBB.matrix, 
          0.0, &CCCC.matrix); 

      MPI_Send(CC,bcols,MPI_DOUBLE_PRECISION, master, crow, MPI_COMM_WORLD); 
      MPI_Recv(buff,nsame,MPI_DOUBLE_PRECISION,master,MPI_ANY_TAG,MPI_COMM_WORLD,&status); 
     } 
    } 

    // output c here on master node //uncomment the below lines if I wish to see the output 
    // if (nid == master){ 
//  if (rowsent == arows){ 
//   //   cout << rowsent; 
//   int IND_F = 0; 
//   while (IND_F < arows){ 
//    int IND_K = 0; 
//    while (IND_K < bcols){ 
//     cout << "[" << IND_F << "]" << "[" << IND_K << "] = " << c[IND_F][IND_K] << " "; 
//     IND_K++; 
//    } 
//    cout << "\n"; 
//    IND_F++; 
//   } 
//  } 
// } 
    MPI_Finalize(); 
    //free any allocated space here 
    return 0; 
}; 

今すぐ奇数見えるもの(私は行列のサイズを大きくする場合ということです例えばnsame = 500からnsame = 501へ)、コードはもう機能しません。私は、次のエラーが表示されます

mpirun noticed that process rank 0 with PID 0 on node Users-MacBook-Air exited on signal 11 (Segmentation fault: 11). 

私は行列の大きさの他の組み合わせでこれを試してみましたが、常に行列自身のサイズには上限が存在すると考えている(どのように私に基づいて異なるように思われ異なる次元自体を変える)。私は行列自体の値を変更しようとしましたが、何も変わらないようです。私の例ではベクトルを使用して行列を初期化する別の方法があることを認識していますが、現在の任意のサイズの行列を乗算する私の現在のスキームが特定の範囲でしか動作しないように思われるのは簡単です。

答えて

2

大きなローカル変数を宣言すると、スタック領域に関連する問題が発生します。 aは、特に500x500倍(250000 8バイト要素、または200万バイト)です。 bはさらに大きくなります。

これらの配列の一部またはすべてに動的に領域を割り当てる必要があります。

最初のスタック領域を増やすためのコンパイラオプションがあるかもしれませんが、それは長期的には良い解決策ではありません。

関連する問題