]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/ParaMEDMEMTest/MPI2Connector.cxx
Salome HOME
Build MEDCOUPLING with native openmpi on CentOS-8
[tools/medcoupling.git] / src / ParaMEDMEMTest / MPI2Connector.cxx
1 // Copyright (C) 2007-2020  CEA/DEN, EDF R&D
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 "MPI2Connector.hxx"
21
22 #include <iostream>
23 #include <cstring>
24
25 #ifndef WIN32
26 #include <unistd.h>
27 #endif
28
29 #if OMPI_MAJOR_VERSION >= 4
30 #define MPI_ERROR_HANDLER(var) MPI_Comm_set_errhandler(MPI_COMM_WORLD, var);
31 #else
32 #define MPI_ERROR_HANDLER(var) MPI_Errhandler_set(MPI_COMM_WORLD, var);
33 #endif
34
35 MPI2Connector::MPI2Connector()
36 {
37   MPI_Comm_size( MPI_COMM_WORLD, &_nb_proc );
38   MPI_Comm_rank( MPI_COMM_WORLD, &_num_proc );
39 }
40
41 MPI2Connector::~MPI2Connector()
42 {
43 }
44
45 MPI_Comm MPI2Connector::remoteMPI2Connect(const std::string& service)
46 {
47   int i;
48   char port_name[MPI_MAX_PORT_NAME];
49   char port_name_clt[MPI_MAX_PORT_NAME];
50   std::ostringstream msg;
51   MPI_Comm icom;
52
53   if( service.size() == 0 )
54     {
55       msg << "[" << _num_proc << "] You have to give a service name !";
56       std::cerr << msg.str().c_str() << std::endl;
57       throw std::exception();
58     }
59
60   _srv = false;
61
62   MPI_Barrier(MPI_COMM_WORLD);
63   MPI_ERROR_HANDLER(MPI_ERRORS_RETURN);
64   if( _num_proc == 0 )
65     { 
66       /* rank 0 try to be a server. If service is already published, try to be a cient */
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         {
70           std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
71           MPI_Close_port( port_name );
72         }
73       else if ( MPI_Publish_name((char*)service.c_str(), MPI_INFO_NULL, port_name) == MPI_SUCCESS )
74         {
75           _srv = true;
76           _port_name = port_name;
77           std::cerr << "[" << _num_proc << "] service " << service << " available at " << port_name << std::endl;
78         }      
79       else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
80         {
81           std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
82           MPI_Close_port( port_name );
83         }
84       else
85         {
86           msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
87           std::cerr << msg.str().c_str() << std::endl;
88           throw std::exception();
89         }
90     }
91   else
92     {
93       i=0;
94       /* Waiting rank 0 publish name and try to be a client */
95       while ( i != TIMEOUT  ) 
96         {
97           sleep(1);
98           if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
99             {
100               std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
101               break;
102             }
103           i++;
104         }
105       if(i==TIMEOUT)
106         {
107           msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
108           std::cerr << msg.str().c_str() << std::endl;
109           throw std::exception();
110         }
111     }
112   MPI_ERROR_HANDLER(MPI_ERRORS_ARE_FATAL);
113   
114   /* If rank 0 is server, all processes call MPI_Comm_accept */
115   /* If rank 0 is not server, all processes call MPI_Comm_connect */
116   int srv = (int)_srv;
117   MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
118   _srv = (bool)srv;
119   if ( _srv )
120     MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
121   else
122     MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
123
124   /* create global communicator: servers have low index in global communicator*/
125   MPI_Intercomm_merge(icom,!_srv,&_gcom);
126
127   /* only rank 0 can be server for unpublish name */
128   if(_num_proc != 0) _srv = false;
129
130   return _gcom;
131
132 }
133
134 void MPI2Connector::remoteMPI2Disconnect(const std::string& service)
135 {
136   std::ostringstream msg;
137
138   if( service.size() == 0 )
139     {
140       msg << "[" << _num_proc << "] You have to give a service name !";
141       std::cerr << msg.str().c_str() << std::endl;
142       throw std::exception();
143     }
144
145   MPI_Comm_disconnect( &_gcom ); 
146   if ( _srv )
147     {
148
149       char port_name[MPI_MAX_PORT_NAME];
150       strcpy(port_name,_port_name.c_str());
151
152       MPI_Unpublish_name((char*)service.c_str(), MPI_INFO_NULL, port_name); 
153       std::cerr << "[" << _num_proc << "] " << service << ": close port " << _port_name << std::endl;
154       MPI_Close_port( port_name ); 
155     }
156   
157 }
158