Salome HOME
d55645256c3f933f0c2a04b8a1850f1324cc9b41
[modules/kernel.git] / src / MPIContainer / testMPI2.cxx
1 // Copyright (C) 2011-2020  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include <iostream>
21 #include <math.h>
22 #include <mpi.h>
23 #include <stdlib.h>
24 #define TIMEOUT 20
25 #define EPSILON 0.00000001
26
27 #ifndef WIN32
28 # include <unistd.h>
29 #endif
30
31 int main(int argc, char**argv)
32 {
33   int *indg;
34   double *vector, sum=0., norm=1., etalon=0.;
35   int rank, size, grank, gsize, rsize;
36   int vsize=20, lvsize, rlvsize;
37   int i, k1, k2, imin, imax, nb;
38   int srv=0;
39   MPI_Comm com, icom;
40   MPI_Status status;
41   MPI_Info info;
42   char   port_name     [MPI_MAX_PORT_NAME]; 
43   char   port_name_clt [MPI_MAX_PORT_NAME]; 
44   std::string service = "SERVICE";
45   bool debug=false;
46
47   for(i=1;i<argc;i++){
48     std::string sargv = argv[i];
49     if(sargv.find("-debug")!=std::string::npos)
50       debug = true;
51     else if(sargv.find("-vsize")!=std::string::npos)
52       vsize = atoi(argv[++i]);
53   }
54
55   MPI_Init( &argc, &argv );
56
57   MPI_Comm_size( MPI_COMM_WORLD, &size );
58   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
59
60   MPI_Barrier(MPI_COMM_WORLD);
61
62   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
63 #ifdef HAVE_MPI2
64   MPI_Info_create(&info);
65   MPI_Info_set(info, "ompi_unique", "true");
66   if(rank==0){
67     MPI_Open_port(MPI_INFO_NULL, port_name); 
68     if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
69       if(debug)
70         std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;
71       MPI_Close_port( port_name );
72     } 
73     else if ( MPI_Publish_name((char*)service.c_str(), info, port_name) == MPI_SUCCESS )  {
74       if(debug)
75         std::cout << "[" << rank << "] I am server: I've managed to publish the service " << service << " !" << std::endl;
76       srv = 1;
77     }      
78     else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
79       if(debug)
80         std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;;
81       MPI_Close_port( port_name );
82     } 
83     else{
84       if(debug)
85         std::cout << "[" << rank << "] ERROR!!!" << std::endl;
86       MPI_Finalize(); 
87       exit(1);
88     }
89   }
90   else{
91     i = 0;
92     while ( i != TIMEOUT  ) { 
93       sleep(1);
94       if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
95         if(debug)
96           std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;
97         break;
98       } 
99       i++;
100     }
101     if ( i == TIMEOUT ) {
102       if(debug)
103         std::cout << "[" << rank << "] Waiting too long exiting !" << std::endl;
104       MPI_Finalize(); 
105       exit(1);
106     }
107   }
108   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL);
109   MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
110   if ( srv )
111     MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
112   else
113     MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
114
115   MPI_Intercomm_merge(icom,!srv,&com);
116
117   MPI_Comm_rank( com, &grank );
118   MPI_Comm_size( com, &gsize );
119
120   MPI_Barrier(com);
121   lvsize = ((rank+1)*vsize) / size - (rank*vsize) / size;
122   vector = (double*)malloc(lvsize*sizeof(double));
123   indg = (int*)malloc(lvsize*sizeof(int));
124   rsize = gsize - size;
125
126   for(i=0;i<lvsize;i++){
127     indg[i] = (rank*vsize)/size + i;
128     if(srv){
129       if(debug)
130         vector[i] = indg[i];
131       else
132         vector[i] = 2. * sin( (rank*vsize)/size + i );
133       sum += vector[i]*vector[i];
134     }
135   }
136   MPI_Barrier(com);
137   if(srv){
138     MPI_Reduce(&sum,&norm,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
139     if(rank==0){
140       norm = sqrt(norm);
141       if(debug)
142         std::cout << "[" << grank << "] norm=" << norm << std::endl;
143     }
144   }
145
146   for(i=0;i<rsize;i++){
147     rlvsize = ((i+1)*vsize) / rsize - (i*vsize) / rsize;
148     k1 = (i*vsize)/rsize;
149     k2 = ((i+1)*vsize)/rsize -1;
150
151     if( (k1 <= indg[lvsize-1]) && (k2 >= indg[0]) ){
152       imin = k1;
153       if( indg[0] > imin ) imin = indg[0];
154       imax = k2;
155       if( indg[lvsize-1] < imax) imax = indg[lvsize-1];
156       if(srv){
157         nb = imax - imin + 1;
158         MPI_Send( &nb, 1, MPI_INT, i+size, 100, com );
159         MPI_Send( vector+imin-indg[0], nb, MPI_DOUBLE, i+size, 200, com );
160       }
161       else{
162         MPI_Recv( &nb, 1, MPI_INT, i, 100, com, &status );
163         MPI_Recv( vector+imin-indg[0], nb, MPI_DOUBLE, i, 200, com, &status );
164       }
165     }
166   }
167
168   MPI_Barrier(com);
169   if(!srv){
170     sum = 0.;
171     sleep(grank);
172     for(i=0;i<lvsize;i++){
173       if(debug)
174         std::cout << "[" << rank << "] vector[" << i << "]=" << vector[i] << std::endl;
175       sum += vector[i]*vector[i];
176     }
177     MPI_Reduce(&sum,&norm,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
178     if(rank==0){
179       norm = sqrt(norm);
180       if(debug)
181         std::cout << "[" << grank << "] norm=" << norm << std::endl;
182     }
183   }
184
185   MPI_Barrier(com);
186   if(srv){
187     if(rank==0){
188       MPI_Recv(&etalon, 1, MPI_DOUBLE,size,400,com, &status);
189       MPI_Send(&norm,1,MPI_DOUBLE, size, 300, com);
190     }
191   }
192   else if(rank==0){
193     MPI_Send(&norm,1,MPI_DOUBLE, 0, 400, com);
194     MPI_Recv(&etalon, 1, MPI_DOUBLE,0,300,com, &status);
195   }
196
197   MPI_Barrier(com);
198   if(rank!=0) srv = 0;
199
200   MPI_Comm_disconnect( &com ); 
201   if ( srv ) {
202     MPI_Unpublish_name((char*)service.c_str(), MPI_INFO_NULL, port_name); 
203     MPI_Close_port( port_name ); 
204   }
205
206   free(indg);
207   free(vector);
208 #endif
209   MPI_Finalize();
210
211   if(rank==0){
212     if(fabs(norm-etalon)/norm < EPSILON ){
213       if(debug)
214         std::cout << "OK" << std::endl;
215       exit(0);
216     }
217     else{
218       if(debug)
219         std::cout << "KO" << std::endl;
220       exit(1);
221     }
222   }
223
224 }