1 // Copyright (C) 2007-2020 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"
29 #if OMPI_MAJOR_VERSION >= 4
30 #define MPI_ERROR_HANDLER(var) MPI_Comm_set_errhandler(MPI_COMM_WORLD, var);
32 #define MPI_ERROR_HANDLER(var) MPI_Errhandler_set(MPI_COMM_WORLD, var);
35 MPI2Connector::MPI2Connector()
37 MPI_Comm_size( MPI_COMM_WORLD, &_nb_proc );
38 MPI_Comm_rank( MPI_COMM_WORLD, &_num_proc );
41 MPI2Connector::~MPI2Connector()
45 MPI_Comm MPI2Connector::remoteMPI2Connect(const std::string& service)
48 char port_name[MPI_MAX_PORT_NAME];
49 char port_name_clt[MPI_MAX_PORT_NAME];
50 std::ostringstream msg;
53 if( service.size() == 0 )
55 msg << "[" << _num_proc << "] You have to give a service name !";
56 std::cerr << msg.str().c_str() << std::endl;
57 throw std::exception();
62 MPI_Barrier(MPI_COMM_WORLD);
63 MPI_ERROR_HANDLER(MPI_ERRORS_RETURN);
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 )
70 std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
71 MPI_Close_port( port_name );
73 else if ( MPI_Publish_name((char*)service.c_str(), MPI_INFO_NULL, port_name) == MPI_SUCCESS )
76 _port_name = port_name;
77 std::cerr << "[" << _num_proc << "] service " << service << " available at " << port_name << std::endl;
79 else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
81 std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
82 MPI_Close_port( port_name );
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();
94 /* Waiting rank 0 publish name and try to be a client */
95 while ( i != TIMEOUT )
98 if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
100 std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
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();
112 MPI_ERROR_HANDLER(MPI_ERRORS_ARE_FATAL);
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 */
117 MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
120 MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
122 MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
124 /* create global communicator: servers have low index in global communicator*/
125 MPI_Intercomm_merge(icom,!_srv,&_gcom);
127 /* only rank 0 can be server for unpublish name */
128 if(_num_proc != 0) _srv = false;
134 void MPI2Connector::remoteMPI2Disconnect(const std::string& service)
136 std::ostringstream msg;
138 if( service.size() == 0 )
140 msg << "[" << _num_proc << "] You have to give a service name !";
141 std::cerr << msg.str().c_str() << std::endl;
142 throw std::exception();
145 MPI_Comm_disconnect( &_gcom );
149 char port_name[MPI_MAX_PORT_NAME];
150 strcpy(port_name,_port_name.c_str());
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 );