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