diff --git a/nestkernel/nest_names.cpp b/nestkernel/nest_names.cpp index 393c11baf1..1eed7b4866 100644 --- a/nestkernel/nest_names.cpp +++ b/nestkernel/nest_names.cpp @@ -287,6 +287,7 @@ const Name min( "min" ); const Name min_delay( "min_delay" ); const Name min_update_time( "min_update_time" ); const Name minor_axis( "minor_axis" ); +const Name mpi_address( "mpi_address" ); const Name model( "model" ); const Name model_id( "model_id" ); const Name ms_per_tic( "ms_per_tic" ); diff --git a/nestkernel/nest_names.h b/nestkernel/nest_names.h index efb9f826d2..03caa15f0c 100644 --- a/nestkernel/nest_names.h +++ b/nestkernel/nest_names.h @@ -312,6 +312,7 @@ extern const Name min; extern const Name min_delay; extern const Name min_update_time; extern const Name minor_axis; +extern const Name mpi_address; extern const Name model; extern const Name model_id; extern const Name ms_per_tic; diff --git a/nestkernel/recording_backend_mpi.cpp b/nestkernel/recording_backend_mpi.cpp index aa059b6156..3c048211a0 100644 --- a/nestkernel/recording_backend_mpi.cpp +++ b/nestkernel/recording_backend_mpi.cpp @@ -69,7 +69,7 @@ nest::RecordingBackendMPI::finalize() } void -nest::RecordingBackendMPI::enroll( const RecordingDevice& device, const DictionaryDatum& ) +nest::RecordingBackendMPI::enroll( const RecordingDevice& device, const DictionaryDatum& params ) { if ( device.get_type() == RecordingDevice::SPIKE_RECORDER ) { @@ -85,6 +85,8 @@ nest::RecordingBackendMPI::enroll( const RecordingDevice& device, const Dictiona std::tuple< int, MPI_Comm*, const RecordingDevice* > tuple = std::make_tuple( -1, nullptr, &device ); devices_[ tid ].insert( std::make_pair( node_id, tuple ) ); enrolled_ = true; + + updateValue< std::string >( params, names::mpi_address, mpi_address_ ); } else { @@ -359,7 +361,22 @@ nest::RecordingBackendMPI::set_status( const DictionaryDatum& ) void nest::RecordingBackendMPI::get_port( const RecordingDevice* device, std::string* port_name ) { - get_port( device->get_node_id(), device->get_label(), port_name ); + const std::string& label = device->get_label(); + + // The MPI address can be provided by two different means. + // a) the address is given via the mpi_address device status + // b) the file is provided via a file: {data_path}/{data_prefix}{label}/{node_id}.txt + + // Case a: MPI address is given via device status, use the supplied address + if ( not mpi_address_.empty() ) + { + *port_name = mpi_address_; + } + // Case b: fallback to get_port implementation that reads the address from file + else + { + get_port( device->get_node_id(), label, port_name ); + } } void diff --git a/nestkernel/recording_backend_mpi.h b/nestkernel/recording_backend_mpi.h index 7db492bbcd..dd9d8f673d 100644 --- a/nestkernel/recording_backend_mpi.h +++ b/nestkernel/recording_backend_mpi.h @@ -47,9 +47,13 @@ Description The `mpi` recording backend sends collected data to a remote process using MPI. -The name of the MPI port to send data to is read from a file for each -device configured to use this backend. The file needs to be named -according to the following pattern: +There are two ways to set the MPI port. If both are set, option A has precedence + +1. The address is supplied via the recording backends "mpi_address" status property. + +2. The name of the MPI port to send data to is read from a file for each + device configured to use this backend. The file needs to be named + according to the following pattern: :: @@ -169,11 +173,15 @@ class RecordingBackendMPI : public RecordingBackend typedef std::map< std::string, std::tuple< int, MPI_Comm*, int > > comm_map; comm_map commMap_; - static void get_port( const RecordingDevice* device, std::string* port_name ); - static void get_port( size_t index_node, const std::string& label, std::string* port_name ); - static void send_data( const MPI_Comm* comm, const double data[], int size ); + + std::string mpi_address_; + + void get_port( const RecordingDevice* device, std::string* port_name ); + void get_port( size_t index_node, const std::string& label, std::string* port_name ); + void send_data( const MPI_Comm* comm, const double data[], int size ); }; + } // namespace #endif /* #ifndef RECORDING_BACKEND_MPI_H */ diff --git a/nestkernel/stimulation_backend_mpi.cpp b/nestkernel/stimulation_backend_mpi.cpp index 521a2a55da..189207f08f 100644 --- a/nestkernel/stimulation_backend_mpi.cpp +++ b/nestkernel/stimulation_backend_mpi.cpp @@ -63,7 +63,7 @@ nest::StimulationBackendMPI::finalize() } void -nest::StimulationBackendMPI::enroll( nest::StimulationDevice& device, const DictionaryDatum& ) +nest::StimulationBackendMPI::enroll( nest::StimulationDevice& device, const DictionaryDatum& params ) { size_t tid = device.get_thread(); size_t node_id = device.get_node_id(); @@ -79,6 +79,9 @@ nest::StimulationBackendMPI::enroll( nest::StimulationDevice& device, const Dict std::pair< size_t, std::pair< const MPI_Comm*, StimulationDevice* > > secondpair = std::make_pair( node_id, pair ); devices_[ tid ].insert( secondpair ); enrolled_ = true; + + // Try to read the mpi_address from the device status + updateValue< std::string >( params, names::mpi_address, mpi_address_ ); } @@ -285,7 +288,21 @@ nest::StimulationBackendMPI::cleanup() void nest::StimulationBackendMPI::get_port( nest::StimulationDevice* device, std::string* port_name ) { - get_port( device->get_node_id(), device->get_label(), port_name ); + const std::string& label = device->get_label(); + // The MPI address can be provided by two different means. + // a) the address is given via the mpi_address device status + // b) the file is provided via a file: {data_path}/{data_prefix}{label}/{node_id}.txt + + // Case a: MPI address is given via device status, use the supplied address + if ( not mpi_address_.empty() ) + { + *port_name = mpi_address_; + } + // Case b: fallback to get_port implementation that reads the address from file + else + { + get_port( device->get_node_id(), label, port_name ); + } } void diff --git a/nestkernel/stimulation_backend_mpi.h b/nestkernel/stimulation_backend_mpi.h index bcf67de572..d06427c741 100644 --- a/nestkernel/stimulation_backend_mpi.h +++ b/nestkernel/stimulation_backend_mpi.h @@ -47,9 +47,13 @@ The `mpi` stimulation backend collects data from MPI channels and updates stimulation devices just before each run. This is useful for co-simulation or for receiving stimuli from external software. -The name of the MPI port to receive data on is read from a file for -each device configured to use this backend. The file needs to be -named according to the following pattern: +There are two ways to set the MPI port. If both are set, option A has precedence + +1. The address is supplied via the recording backends "mpi_address" status property. + +2. The name of the MPI port to send data to is read from a file for each + device configured to use this backend. The file needs to be named + according to the following pattern: :: @@ -150,14 +154,15 @@ class StimulationBackendMPI : public StimulationBackend typedef std::map< std::string, std::tuple< MPI_Comm*, std::vector< int >*, int* > > comm_map; comm_map commMap_; + std::string mpi_address_; /** * Getting the port name for the MPI connection * * @param device : input device for finding the file with the port * @param port_name : result of the port name */ - static void get_port( StimulationDevice* device, std::string* port_name ); - static void get_port( size_t index_node, const std::string& label, std::string* port_name ); + void get_port( StimulationDevice* device, std::string* port_name ); + void get_port( size_t index_node, const std::string& label, std::string* port_name ); /** * MPI communication for receiving the data before each run. *