00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <iostream>
00024
00025
00026 #include "mpi.h"
00027
00028 using std::cout;
00029 using std::endl;
00030
00031 extern "C"
00032 {
00033 void Cblacs_pinfo (int* mypnum, int* nprocs);
00034 void Cblacs_get (int context, int request, int* value);
00035 int Cblacs_gridinit (int* context, char * order, int np_row, int np_col);
00036 void Cblacs_gridinfo (int context, int* np_row, int* np_col, int* my_row, int* my_col);
00037 void Cblacs_gridexit (int context);
00038 void Cblacs_exit (int error_code);
00039 int numroc_ (int *n, int *nb, int *iproc, int *isrcproc, int *nprocs);
00040 void descinit_ (int *desc, int *m, int *n, int *mb, int *nb, int *irsrc, int *icsrc, int *ictxt, int *lld, int *info);
00041 double pdlamch_ (int *ictxt , char *cmach);
00042 double pdlange_ (char *norm, int *m, int *n, double *A, int *ia, int *ja, int *desca, double *work);
00043 void pdlacpy_ (char *uplo, int *m, int *n, double *a, int *ia, int *ja, int *desca, double *b, int *ib, int *jb, int *descb);
00044 void pdgesv_ (int *n, int *nrhs, double *A, int *ia, int *ja, int *desca, int* ipiv, double *B, int *ib, int *jb, int *descb, int *info);
00045 void pdgemm_ (char *TRANSA, char *TRANSB, int * M, int * N, int * K, double * ALPHA,
00046 double * A, int * IA, int * JA, int * DESCA, double * B, int * IB, int * JB, int * DESCB,
00047 double * BETA, double * C, int * IC, int * JC, int * DESCC );
00048 int indxg2p_ (int *indxglob, int *nb, int *iproc, int *isrcproc, int *nprocs);
00049 }
00050
00051 int main(int argc, char **argv)
00052 {
00053
00054 MPI::Init(argc, argv);
00055 int rank = MPI::COMM_WORLD.Get_rank();
00056 int size = MPI::COMM_WORLD.Get_size();
00057
00058
00059 cout << "Process #" << rank << " of " << size << " processes just started ...\n";
00060 cout << "" << endl;
00061
00062
00063 int n = 500;
00064 int nrhs = 1;
00065 int nprow = 2;
00066 int npcol = 2;
00067 int nb = 64;
00068
00069
00070 if (nb>n) nb=n;
00071 if (nprow*npcol>size)
00072 {
00073 if (rank==0)
00074 {
00075 cout << "ERROR: There is not enough processes (" << size << "<" << nprow*npcol << ") to make a p-by-q process grid" << endl;
00076 MPI::Finalize();
00077 return 1;
00078 }
00079 }
00080
00081
00082 int iam, nprocs, ictxt;
00083 int myrow, mycol;
00084 Cblacs_pinfo (&iam, &nprocs);
00085 Cblacs_get (-1, 0, &ictxt);
00086 Cblacs_gridinit (&ictxt, "Col", nprow, npcol);
00087 Cblacs_gridinfo (ictxt, &nprow, &npcol, &myrow, &mycol);
00088
00089
00090 if ((myrow>-1)&&(mycol>-1)&&(myrow<nprow)&&(mycol<npcol))
00091 {
00092
00093 int izero = 0;
00094 int np = numroc_(&n , &nb, &myrow, &izero, &nprow);
00095 int nq = numroc_(&n , &nb, &mycol, &izero, &npcol);
00096 int nqrhs = numroc_(&nrhs, &nb, &mycol, &izero, &npcol);
00097
00098
00099 double * A = new double [np*nq];
00100 double * Acpy = new double [np*nq];
00101 double * B = new double [np*nqrhs];
00102 double * X = new double [np*nqrhs];
00103 double * R = new double [np*nqrhs];
00104 int * ippiv = new int [np+nb];
00105
00106
00107 int k=0;
00108 for (int i=0; i<np; i++)
00109 for (int j=0; j<nq; j++)
00110 {
00111 A[k] = ((double) rand()) / ((double) RAND_MAX) - 0.5;
00112 k++;
00113 }
00114
00115
00116 k=0;
00117 for (int i=0; i<np; i++)
00118 for (int j=0; j<nqrhs; j++)
00119 {
00120 B[k] = ((double) rand()) / ((double) RAND_MAX) - 0.5;
00121 k++;
00122 }
00123
00124
00125 int itemp = (np<1 ? 1 : np);
00126 int descA[9];
00127 int descB[9];
00128 int info;
00129 descinit_(descA, &n, &n , &nb, &nb, &izero, &izero, &ictxt, &itemp, &info);
00130 descinit_(descB, &n, &nrhs, &nb, &nb, &izero, &izero, &ictxt, &itemp, &info);
00131
00132
00133 int ione = 1;
00134 pdlacpy_("All", &n, &n , A, &ione, &ione, descA, Acpy, &ione, &ione, descA);
00135 pdlacpy_("All", &n, &nrhs, B, &ione, &ione, descB, X , &ione, &ione, descB);
00136
00137
00138 double MPIt1 = MPI::Wtime();
00139 pdgesv_(&n, &nrhs, A, &ione, &ione, descA, ippiv, X, &ione, &ione, descB, &info);
00140 double MPIt2 = MPI::Wtime();
00141 double MPIelapsed = MPIt2-MPIt1;
00142
00143
00144 double mone=-1.0;
00145 double pone= 1.0;
00146 pdlacpy_("All", &n, &nrhs, B, &ione, &ione, descB, R, &ione, &ione, descB);
00147 pdgemm_ ("N", "N", &n, &nrhs, &n, &pone, Acpy, &ione, &ione, descA, X, &ione, &ione, descB, &mone, R, &ione, &ione, descB);
00148 double work = 0.0;
00149 double eps = pdlamch_(&ictxt, "Epsilon");
00150 double AnormF = pdlange_("F", &n, &n , A, &ione, &ione, descA, &work);
00151 double XnormF = pdlange_("F", &n, &nrhs, X, &ione, &ione, descB, &work);
00152 double RnormF = pdlange_("F", &n, &nrhs, R, &ione, &ione, descB, &work);
00153 double residF = RnormF/(AnormF*XnormF*eps*static_cast<double>(n));
00154
00155
00156 if (iam==0)
00157 {
00158 cout << endl;
00159 cout << "***********************************************" << endl;
00160 cout << " Example of ScaLAPACK routine call: (PDGESV) " << endl;
00161 cout << "***********************************************" << endl;
00162 cout << endl;
00163 cout << " n = " << n << endl;
00164 cout << " nrhs = " << nrhs << endl;
00165 cout << " grid = " << nprow << ", " << npcol << endl;
00166 cout << " blocks = " << nb << "x" << nb << endl;
00167 cout << " np = " << np << endl;
00168 cout << " nq = " << nq << endl;
00169 cout << " nqrhs = " << nqrhs << endl;
00170 cout << endl;
00171 cout << "MPI elapsed time during (pdgesv) = " << MPIelapsed << endl;
00172 cout << "Info returned by (pdgesv) = " << info << endl;
00173 cout << endl;
00174 cout << "Froebenius norm (residual) = " << residF << endl;
00175 cout << endl;
00176 }
00177
00178
00179 delete [] A;
00180 delete [] Acpy;
00181 delete [] B;
00182 delete [] X;
00183 delete [] R;
00184 delete [] ippiv;
00185
00186
00187 Cblacs_gridexit(0);
00188 }
00189
00190
00191 if(iam==0)
00192 {
00193 cout << "***********************************************\n";
00194 cout << " END \n";
00195 cout << "***********************************************\n";
00196 }
00197
00198
00199 MPI::Finalize();
00200
00201 return 0;
00202 }
00203
00204