Salome HOME
Build KERNEL with native openmpi on CentOS-8
[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 #if OMPI_MAJOR_VERSION >= 4
62   MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
63 #else
64   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
65 #endif
66
67 #ifdef HAVE_MPI2
68   MPI_Info_create(&info);
69   MPI_Info_set(info, "ompi_unique", "true");
70   if(rank==0){
71     MPI_Open_port(MPI_INFO_NULL, port_name); 
72     if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
73       if(debug)
74         std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;
75       MPI_Close_port( port_name );
76     } 
77     else if ( MPI_Publish_name((char*)service.c_str(), info, port_name) == MPI_SUCCESS )  {
78       if(debug)
79         std::cout << "[" << rank << "] I am server: I've managed to publish the service " << service << " !" << std::endl;
80       srv = 1;
81     }      
82     else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
83       if(debug)
84         std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;;
85       MPI_Close_port( port_name );
86     } 
87     else{
88       if(debug)
89         std::cout << "[" << rank << "] ERROR!!!" << std::endl;
90       MPI_Finalize(); 
91       exit(1);
92     }
93   }
94   else{
95     i = 0;
96     while ( i != TIMEOUT  ) { 
97       sleep(1);
98       if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
99         if(debug)
100           std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;
101         break;
102       } 
103       i++;
104     }
105     if ( i == TIMEOUT ) {
106       if(debug)
107         std::cout << "[" << rank << "] Waiting too long exiting !" << std::endl;
108       MPI_Finalize(); 
109       exit(1);
110     }
111   }
112 #if OMPI_MAJOR_VERSION >= 4
113   MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL);
114 #else
115   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL);
116 #endif
117   MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
118   if ( srv )
119     MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
120   else
121     MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
122
123   MPI_Intercomm_merge(icom,!srv,&com);
124
125   MPI_Comm_rank( com, &grank );
126   MPI_Comm_size( com, &gsize );
127
128   MPI_Barrier(com);
129   lvsize = ((rank+1)*vsize) / size - (rank*vsize) / size;
130   vector = (double*)malloc(lvsize*sizeof(double));
131   indg = (int*)malloc(lvsize*sizeof(int));
132   rsize = gsize - size;
133
134   for(i=0;i<lvsize;i++){
135     indg[i] = (rank*vsize)/size + i;
136     if(srv){
137       if(debug)
138         vector[i] = indg[i];
139       else
140         vector[i] = 2. * sin( (rank*vsize)/size + i );
141       sum += vector[i]*vector[i];
142     }
143   }
144   MPI_Barrier(com);
145   if(srv){
146     MPI_Reduce(&sum,&norm,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
147     if(rank==0){
148       norm = sqrt(norm);
149       if(debug)
150         std::cout << "[" << grank << "] norm=" << norm << std::endl;
151     }
152   }
153
154   for(i=0;i<rsize;i++){
155     rlvsize = ((i+1)*vsize) / rsize - (i*vsize) / rsize;
156     k1 = (i*vsize)/rsize;
157     k2 = ((i+1)*vsize)/rsize -1;
158
159     if( (k1 <= indg[lvsize-1]) && (k2 >= indg[0]) ){
160       imin = k1;
161       if( indg[0] > imin ) imin = indg[0];
162       imax = k2;
163       if( indg[lvsize-1] < imax) imax = indg[lvsize-1];
164       if(srv){
165         nb = imax - imin + 1;
166         MPI_Send( &nb, 1, MPI_INT, i+size, 100, com );
167         MPI_Send( vector+imin-indg[0], nb, MPI_DOUBLE, i+size, 200, com );
168       }
169       else{
170         MPI_Recv( &nb, 1, MPI_INT, i, 100, com, &status );
171         MPI_Recv( vector+imin-indg[0], nb, MPI_DOUBLE, i, 200, com, &status );
172       }
173     }
174   }
175
176   MPI_Barrier(com);
177   if(!srv){
178     sum = 0.;
179     sleep(grank);
180     for(i=0;i<lvsize;i++){
181       if(debug)
182         std::cout << "[" << rank << "] vector[" << i << "]=" << vector[i] << std::endl;
183       sum += vector[i]*vector[i];
184     }
185     MPI_Reduce(&sum,&norm,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
186     if(rank==0){
187       norm = sqrt(norm);
188       if(debug)
189         std::cout << "[" << grank << "] norm=" << norm << std::endl;
190     }
191   }
192
193   MPI_Barrier(com);
194   if(srv){
195     if(rank==0){
196       MPI_Recv(&etalon, 1, MPI_DOUBLE,size,400,com, &status);
197       MPI_Send(&norm,1,MPI_DOUBLE, size, 300, com);
198     }
199   }
200   else if(rank==0){
201     MPI_Send(&norm,1,MPI_DOUBLE, 0, 400, com);
202     MPI_Recv(&etalon, 1, MPI_DOUBLE,0,300,com, &status);
203   }
204
205   MPI_Barrier(com);
206   if(rank!=0) srv = 0;
207
208   MPI_Comm_disconnect( &com ); 
209   if ( srv ) {
210     MPI_Unpublish_name((char*)service.c_str(), MPI_INFO_NULL, port_name); 
211     MPI_Close_port( port_name ); 
212   }
213
214   free(indg);
215   free(vector);
216 #endif
217   MPI_Finalize();
218
219   if(rank==0){
220     if(fabs(norm-etalon)/norm < EPSILON ){
221       if(debug)
222         std::cout << "OK" << std::endl;
223       exit(0);
224     }
225     else{
226       if(debug)
227         std::cout << "KO" << std::endl;
228       exit(1);
229     }
230   }
231
232 }