Salome HOME
Porting to OCCT 7.8.0
[modules/kernel.git] / src / MPIContainer / testMPI2.cxx
1 // Copyright (C) 2011-2024  CEA, EDF, 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 #include "Basics_MpiUtils.hxx"
32
33 int main(int argc, char**argv)
34 {
35   int *indg;
36   double *vector, sum=0., norm=1., etalon=0.;
37   int rank, size, grank, gsize, rsize;
38   int vsize=20, lvsize;
39   //int rlvsize;
40   int i, k1, k2, imin, imax, nb;
41   int srv=0;
42   MPI_Comm com, icom;
43   MPI_Status status;
44   MPI_Info info;
45   char   port_name     [MPI_MAX_PORT_NAME]; 
46   char   port_name_clt [MPI_MAX_PORT_NAME]; 
47   std::string service = "SERVICE";
48   bool debug=false;
49
50   for(i=1;i<argc;i++){
51     std::string sargv = argv[i];
52     if(sargv.find("-debug")!=std::string::npos)
53       debug = true;
54     else if(sargv.find("-vsize")!=std::string::npos)
55       vsize = atoi(argv[++i]);
56   }
57
58   MPI_Init( &argc, &argv );
59
60   MPI_Comm_size( MPI_COMM_WORLD, &size );
61   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
62
63   MPI_Barrier(MPI_COMM_WORLD);
64   MPI_ERROR_HANDLER(MPI_ERRORS_RETURN);
65
66 #ifdef HAVE_MPI2
67   MPI_Info_create(&info);
68   MPI_Info_set(info, "ompi_unique", "true");
69   if(rank==0){
70     MPI_Open_port(MPI_INFO_NULL, port_name); 
71     if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
72       if(debug)
73         std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;
74       MPI_Close_port( port_name );
75     } 
76     else if ( MPI_Publish_name((char*)service.c_str(), info, port_name) == MPI_SUCCESS )  {
77       if(debug)
78         std::cout << "[" << rank << "] I am server: I've managed to publish the service " << service << " !" << std::endl;
79       srv = 1;
80     }      
81     else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
82       if(debug)
83         std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;;
84       MPI_Close_port( port_name );
85     } 
86     else{
87       if(debug)
88         std::cout << "[" << rank << "] ERROR!!!" << std::endl;
89       MPI_Finalize(); 
90       exit(1);
91     }
92   }
93   else{
94     i = 0;
95     while ( i != TIMEOUT  ) { 
96       sleep(1);
97       if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )  {
98         if(debug)
99           std::cout << "[" << rank << "] I am client: I get the service " << service << " !" << std::endl;
100         break;
101       } 
102       i++;
103     }
104     if ( i == TIMEOUT ) {
105       if(debug)
106         std::cout << "[" << rank << "] Waiting too long exiting !" << std::endl;
107       MPI_Finalize(); 
108       exit(1);
109     }
110   }
111   MPI_ERROR_HANDLER(MPI_ERRORS_ARE_FATAL);
112   MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
113   if ( srv )
114     MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
115   else
116     MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
117
118   MPI_Intercomm_merge(icom,!srv,&com);
119
120   MPI_Comm_rank( com, &grank );
121   MPI_Comm_size( com, &gsize );
122
123   MPI_Barrier(com);
124   lvsize = ((rank+1)*vsize) / size - (rank*vsize) / size;
125   vector = (double*)malloc(lvsize*sizeof(double));
126   indg = (int*)malloc(lvsize*sizeof(int));
127   rsize = gsize - size;
128
129   for(i=0;i<lvsize;i++){
130     indg[i] = (rank*vsize)/size + i;
131     if(srv){
132       if(debug)
133         vector[i] = indg[i];
134       else
135         vector[i] = 2. * sin( (rank*vsize)/size + i );
136       sum += vector[i]*vector[i];
137     }
138   }
139   MPI_Barrier(com);
140   if(srv){
141     MPI_Reduce(&sum,&norm,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
142     if(rank==0){
143       norm = sqrt(norm);
144       if(debug)
145         std::cout << "[" << grank << "] norm=" << norm << std::endl;
146     }
147   }
148
149   for(i=0;i<rsize;i++){
150     //rlvsize = ((i+1)*vsize) / rsize - (i*vsize) / rsize;
151     k1 = (i*vsize)/rsize;
152     k2 = ((i+1)*vsize)/rsize -1;
153
154     if( (k1 <= indg[lvsize-1]) && (k2 >= indg[0]) ){
155       imin = k1;
156       if( indg[0] > imin ) imin = indg[0];
157       imax = k2;
158       if( indg[lvsize-1] < imax) imax = indg[lvsize-1];
159       if(srv){
160         nb = imax - imin + 1;
161         MPI_Send( &nb, 1, MPI_INT, i+size, 100, com );
162         MPI_Send( vector+imin-indg[0], nb, MPI_DOUBLE, i+size, 200, com );
163       }
164       else{
165         MPI_Recv( &nb, 1, MPI_INT, i, 100, com, &status );
166         MPI_Recv( vector+imin-indg[0], nb, MPI_DOUBLE, i, 200, com, &status );
167       }
168     }
169   }
170
171   MPI_Barrier(com);
172   if(!srv){
173     sum = 0.;
174     sleep(grank);
175     for(i=0;i<lvsize;i++){
176       if(debug)
177         std::cout << "[" << rank << "] vector[" << i << "]=" << vector[i] << std::endl;
178       sum += vector[i]*vector[i];
179     }
180     MPI_Reduce(&sum,&norm,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
181     if(rank==0){
182       norm = sqrt(norm);
183       if(debug)
184         std::cout << "[" << grank << "] norm=" << norm << std::endl;
185     }
186   }
187
188   MPI_Barrier(com);
189   if(srv){
190     if(rank==0){
191       MPI_Recv(&etalon, 1, MPI_DOUBLE,size,400,com, &status);
192       MPI_Send(&norm,1,MPI_DOUBLE, size, 300, com);
193     }
194   }
195   else if(rank==0){
196     MPI_Send(&norm,1,MPI_DOUBLE, 0, 400, com);
197     MPI_Recv(&etalon, 1, MPI_DOUBLE,0,300,com, &status);
198   }
199
200   MPI_Barrier(com);
201   if(rank!=0) srv = 0;
202
203   MPI_Comm_disconnect( &com ); 
204   if ( srv ) {
205     MPI_Unpublish_name((char*)service.c_str(), MPI_INFO_NULL, port_name); 
206     MPI_Close_port( port_name ); 
207   }
208
209   free(indg);
210   free(vector);
211 #endif
212   MPI_Finalize();
213
214   if(rank==0){
215     if(fabs(norm-etalon)/norm < EPSILON ){
216       if(debug)
217         std::cout << "OK" << std::endl;
218       exit(0);
219     }
220     else{
221       if(debug)
222         std::cout << "KO" << std::endl;
223       exit(1);
224     }
225   }
226
227 }