Salome HOME
Fix
[modules/kernel.git] / src / MPIContainer / testMPI2.cxx
1 #include <iostream>
2 #include <math.h>
3 #include <mpi.h>
4 #include <stdlib.h>
5 #define TIMEOUT 20
6 #define EPSILON 0.00000001
7
8 #ifndef WIN32
9 # include <unistd.h>
10 #endif
11
12 int main(int argc, char**argv)
13 {
14   int *indg;
15   double *vector, sum=0., norm, etalon;
16   int rank, size, grank, gsize, rsize;
17   int vsize=20, lvsize, rlvsize;
18   int i, k1, k2, imin, imax, nb;
19   int srv=0;
20   MPI_Comm com, icom;
21   MPI_Status status; 
22   char   port_name     [MPI_MAX_PORT_NAME]; 
23   char   port_name_clt [MPI_MAX_PORT_NAME]; 
24   std::string service = "SERVICE";
25   bool debug=false;
26
27 #ifndef WITHOPENMPI
28   std::cout << "This test only works with openmpi implementation" << std::endl;
29   exit(1);
30 #endif
31
32   for(i=1;i<argc;i++){
33     std::string sargv = argv[i];
34     if(sargv.find("-debug")!=std::string::npos)
35       debug = true;
36     else if(sargv.find("-vsize")!=std::string::npos)
37       vsize = atoi(argv[++i]);
38   }
39
40   MPI_Init( &argc, &argv );
41
42   MPI_Comm_size( MPI_COMM_WORLD, &size );
43   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
44
45   MPI_Barrier(MPI_COMM_WORLD);
46
47   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
48   if(rank==0){
49     MPI_Open_port(MPI_INFO_NULL, port_name); 
50     if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
51       if(debug)
52         std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;
53       MPI_Close_port( port_name );
54     } 
55     else if ( MPI_Publish_name((char*)service.c_str(), MPI_INFO_NULL, port_name) == MPI_SUCCESS )  {
56       if(debug)
57         std::cout << "[" << rank << "] I am server: I've managed to publish the service " << service << " !" << std::endl;
58       srv = 1;
59     }      
60     else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
61       if(debug)
62         std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;;
63       MPI_Close_port( port_name );
64     } 
65     else{
66       if(debug)
67         std::cout << "[" << rank << "] ERROR!!!" << std::endl;
68       MPI_Finalize(); 
69       exit(1);
70     }
71   }
72   else{
73     i = 0;
74     while ( i != TIMEOUT  ) { 
75       sleep(1);
76       if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
77         if(debug)
78           std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;
79         break;
80       } 
81       i++;
82     }
83     if ( i == TIMEOUT ) {
84       if(debug)
85         std::cout << "[" << rank << "] Waiting too long exiting !" << std::endl;
86       MPI_Finalize(); 
87       exit(1);
88     }
89   }
90   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL);
91   MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
92   if ( srv )
93     MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
94   else
95     MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
96
97   MPI_Intercomm_merge(icom,!srv,&com);
98
99   MPI_Comm_rank( com, &grank );
100   MPI_Comm_size( com, &gsize );
101
102   MPI_Barrier(com);
103   lvsize = ((rank+1)*vsize) / size - (rank*vsize) / size;
104   vector = (double*)malloc(lvsize*sizeof(double));
105   indg = (int*)malloc(lvsize*sizeof(int));
106   rsize = gsize - size;
107
108   for(i=0;i<lvsize;i++){
109     indg[i] = (rank*vsize)/size + i;
110     if(srv){
111       if(debug)
112         vector[i] = indg[i];
113       else
114         vector[i] = 2. * sin( (rank*vsize)/size + i );
115       sum += vector[i]*vector[i];
116     }
117   }
118   MPI_Barrier(com);
119   if(srv){
120     MPI_Reduce(&sum,&norm,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
121     if(rank==0){
122       norm = sqrt(norm);
123       if(debug)
124         std::cout << "[" << grank << "] norm=" << norm << std::endl;
125     }
126   }
127
128   for(i=0;i<rsize;i++){
129     rlvsize = ((i+1)*vsize) / rsize - (i*vsize) / rsize;
130     k1 = (i*vsize)/rsize;
131     k2 = ((i+1)*vsize)/rsize -1;
132
133     if( (k1 <= indg[lvsize-1]) && (k2 >= indg[0]) ){
134       imin = k1;
135       if( indg[0] > imin ) imin = indg[0];
136       imax = k2;
137       if( indg[lvsize-1] < imax) imax = indg[lvsize-1];
138       if(srv){
139         nb = imax - imin + 1;
140         MPI_Send( &nb, 1, MPI_INT, i+size, 100, com );
141         MPI_Send( vector+imin-indg[0], nb, MPI_DOUBLE, i+size, 200, com );
142       }
143       else{
144         MPI_Recv( &nb, 1, MPI_INT, i, 100, com, &status );
145         MPI_Recv( vector+imin-indg[0], nb, MPI_DOUBLE, i, 200, com, &status );
146       }
147     }
148   }
149
150   MPI_Barrier(com);
151   if(!srv){
152     sum = 0.;
153     sleep(grank);
154     for(i=0;i<lvsize;i++){
155       if(debug)
156         std::cout << "[" << rank << "] vector[" << i << "]=" << vector[i] << std::endl;
157       sum += vector[i]*vector[i];
158     }
159     MPI_Reduce(&sum,&norm,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
160     if(rank==0){
161       norm = sqrt(norm);
162       if(debug)
163         std::cout << "[" << grank << "] norm=" << norm << std::endl;
164     }
165   }
166
167   MPI_Barrier(com);
168   if(srv){
169     if(rank==0){
170       MPI_Recv(&etalon, 1, MPI_DOUBLE,size,400,com, &status);
171       MPI_Send(&norm,1,MPI_DOUBLE, size, 300, com);
172     }
173   }
174   else if(rank==0){
175     MPI_Send(&norm,1,MPI_DOUBLE, 0, 400, com);
176     MPI_Recv(&etalon, 1, MPI_DOUBLE,0,300,com, &status);
177   }
178
179   MPI_Barrier(com);
180   if(rank!=0) srv = 0;
181
182   MPI_Comm_disconnect( &com ); 
183   if ( srv ) {
184     MPI_Unpublish_name((char*)service.c_str(), MPI_INFO_NULL, port_name); 
185     MPI_Close_port( port_name ); 
186   }
187
188   free(indg);
189   free(vector);
190   MPI_Finalize();
191
192   if(rank==0){
193     if(fabs(norm-etalon)/norm < EPSILON ){
194       if(debug)
195         std::cout << "OK" << std::endl;
196       exit(0);
197     }
198     else{
199       if(debug)
200         std::cout << "KO" << std::endl;
201       exit(1);
202     }
203   }
204
205 }