1 // Copyright (C) 2007-2021 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "MPI2Connector.hxx"
30 #ifdef OMPI_MAJOR_VERSION
31 # if OMPI_MAJOR_VERSION >= 4
32 # define MPI_ERROR_HANDLER(var) MPI_Comm_set_errhandler(MPI_COMM_WORLD, var)
34 # define MPI_ERROR_HANDLER(var) MPI_Errhandler_set(MPI_COMM_WORLD, var)
36 #else // MPICH and other versions:
37 # define MPI_ERROR_HANDLER(var) MPI_Errhandler_set(MPI_COMM_WORLD, var)
40 MPI2Connector::MPI2Connector()
42 MPI_Comm_size( MPI_COMM_WORLD, &_nb_proc );
43 MPI_Comm_rank( MPI_COMM_WORLD, &_num_proc );
46 MPI2Connector::~MPI2Connector()
50 MPI_Comm MPI2Connector::remoteMPI2Connect(const std::string& service)
53 char port_name[MPI_MAX_PORT_NAME];
54 char port_name_clt[MPI_MAX_PORT_NAME];
55 std::ostringstream msg;
58 if( service.size() == 0 )
60 msg << "[" << _num_proc << "] You have to give a service name !";
61 std::cerr << msg.str().c_str() << std::endl;
62 throw std::exception();
67 MPI_Barrier(MPI_COMM_WORLD);
68 MPI_ERROR_HANDLER(MPI_ERRORS_RETURN);
71 /* rank 0 try to be a server. If service is already published, try to be a cient */
72 MPI_Open_port(MPI_INFO_NULL, port_name);
73 if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
75 std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
76 MPI_Close_port( port_name );
78 else if ( MPI_Publish_name((char*)service.c_str(), MPI_INFO_NULL, port_name) == MPI_SUCCESS )
81 _port_name = port_name;
82 std::cerr << "[" << _num_proc << "] service " << service << " available at " << port_name << std::endl;
84 else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
86 std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
87 MPI_Close_port( port_name );
91 msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
92 std::cerr << msg.str().c_str() << std::endl;
93 throw std::exception();
99 /* Waiting rank 0 publish name and try to be a client */
100 while ( i != TIMEOUT )
103 if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
105 std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
112 msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
113 std::cerr << msg.str().c_str() << std::endl;
114 throw std::exception();
117 MPI_ERROR_HANDLER(MPI_ERRORS_ARE_FATAL);
119 /* If rank 0 is server, all processes call MPI_Comm_accept */
120 /* If rank 0 is not server, all processes call MPI_Comm_connect */
122 MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
125 MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
127 MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
129 /* create global communicator: servers have low index in global communicator*/
130 MPI_Intercomm_merge(icom,!_srv,&_gcom);
132 /* only rank 0 can be server for unpublish name */
133 if(_num_proc != 0) _srv = false;
139 void MPI2Connector::remoteMPI2Disconnect(const std::string& service)
141 std::ostringstream msg;
143 if( service.size() == 0 )
145 msg << "[" << _num_proc << "] You have to give a service name !";
146 std::cerr << msg.str().c_str() << std::endl;
147 throw std::exception();
150 MPI_Comm_disconnect( &_gcom );
154 char port_name[MPI_MAX_PORT_NAME];
155 strcpy(port_name,_port_name.c_str());
157 MPI_Unpublish_name((char*)service.c_str(), MPI_INFO_NULL, port_name);
158 std::cerr << "[" << _num_proc << "] " << service << ": close port " << _port_name << std::endl;
159 MPI_Close_port( port_name );