diff --git a/miniapp/io.cpp b/miniapp/io.cpp index 0c9acd016c50ff5cacfe2180533eef9ba3150592..f3cffdeb2cc7c842bbc30be8156ce0e97a15b5ac 100644 --- a/miniapp/io.cpp +++ b/miniapp/io.cpp @@ -133,7 +133,6 @@ cl_options read_options(int argc, char** argv) { options.tfinal = fopts["tfinal"]; options.all_to_all = fopts["all_to_all"]; - // Parameters for spike output options.spike_file_output = fopts["spike_file_output"]; if (options.spike_file_output) { diff --git a/src/communication/communicator.hpp b/src/communication/communicator.hpp index 37b6d44cc4222d7314c1bc0d2ae0915be8f64f55..04baca09cbcbd38e798b4aca4bf9111c06d6c120 100644 --- a/src/communication/communicator.hpp +++ b/src/communication/communicator.hpp @@ -92,18 +92,16 @@ public: /// events in each queue are all events that must be delivered to targets in that cell /// group as a result of the global spike exchange. std::vector<event_queue> exchange(const std::vector<spike_type>& local_spikes, - std::function<void (const std::vector<spike_type>&)> do_export_rank, - std::function<void(const std::vector<spike_type>&)> do_export_single) + std::function<void (const std::vector<spike_type>&)> do_export_local, + std::function<void(const std::vector<spike_type>&)> do_export_global) { - // Export of (rank) local spikes - do_export_rank(local_spikes); + do_export_local(local_spikes); // global all-to-all to gather a local copy of the global spike list on each node. auto global_spikes = communication_policy_.gather_spikes( local_spikes ); num_spikes_ += global_spikes.size(); - // Export of global spikes - do_export_single(global_spikes); + do_export_global(global_spikes); // check each global spike in turn to see it generates local events. // if so, make the events and insert them into the appropriate event list. diff --git a/src/communication/export_manager.hpp b/src/communication/export_manager.hpp index 492be63bca57f0cb0af218f386d9ea47a8b08652..2a05ba19c6d160902a1b7ab69a189c1e82220bc3 100644 --- a/src/communication/export_manager.hpp +++ b/src/communication/export_manager.hpp @@ -19,20 +19,47 @@ namespace nest { namespace mc { namespace communication { + +// export_manager manages the export of simulation parameters to the outside +// world. Examples could be output to disk, but also more advanced communication +// via mpi can be possible. +// The parameters to be exported are buffered locally. +// There are two export methods implemented: rank local where an export is +// done on each rank and a single export per simulation +// The output file is constructed from constructor arguments and will always +// contain a index also when a single file is written. THis allows automated +// parsing with a simple regex +// +// TODO: The exporter currently only exports spikes to file. The constructor +// arguments reflect this. In future version a better way to configure this +// class is needed. template <typename Time, typename CommunicationPolicy> class export_manager { public: using time_type = Time; using spike_type = spike<cell_member_type, time_type>; + + // Constructor + // spike_file_output initiates spike file output. If false the object is + // constructed in a valid state. No exporters are registed so no output + // is done + // single_file_per_rank if true only rank zero performs output to disk + // over_write if true will overwrite the specified output file + // output_path relative or absolute path + // file_name will be appended with "_x" with x the rank number + // file_extention a seperator will be added automatically export_manager(bool spike_file_output, bool single_file_per_rank, bool over_write, std::string output_path, std::string file_name, std::string file_extention) + : + spike_file_output_(spike_file_output) { - if (!spike_file_output) - { + // simple switch to turn of the export, object will still be in a valid + // state. + if (!spike_file_output_) { return; } - // single file per rank + // single file per rank exporters if (single_file_per_rank) { rank_exporters_.push_back( nest::mc::util::make_unique< @@ -40,7 +67,7 @@ public: file_name, output_path, file_extention, over_write)); } - // single file per simulation + // single file per simulation exporters if (!single_file_per_rank) { single_exporters_.push_back( nest::mc::util::make_unique< @@ -49,21 +76,36 @@ public: } } + // Perform a export of local spikes, typically used for exporting to multi- + // ple files from each rank individually. + // spikes are buffer before export void do_export_local(const std::vector<spike_type>& spikes) { + // TODO: No export needed, so exit + if (!spike_file_output_) { + return; + } + local_spikes_.insert(std::end(local_spikes_), std::begin(spikes), std::end(spikes)); - for (auto &exporter : rank_exporters_) - { + // TODO: Do each exporter in a parallel thread? + for (auto &exporter : rank_exporters_) { exporter->do_export(spikes); } local_spikes_.clear(); } + // Perform a export of global spikes, typically used for exporting spikes + // from a single rank in a simulation + // spikes are buffer before export void do_export_global(const std::vector<spike_type>& spikes) { + if (!spike_file_output_) { + return; + } + // We only output on a single rank if (!communication_policy_.id() == 0) { return; @@ -72,9 +114,8 @@ public: global_spikes_.insert(std::end(global_spikes_), std::begin(spikes), std::end(spikes)); - - for (auto &exporter : single_exporters_) - { + // TODO: Do each exporter in a parallel thread? + for (auto &exporter : single_exporters_) { exporter->do_export(spikes); } @@ -82,20 +123,18 @@ public: } private: - // + bool spike_file_output_; + std::vector<std::unique_ptr<exporter_interface<Time, CommunicationPolicy> > > rank_exporters_; - std::vector<std::unique_ptr<exporter_interface<Time, CommunicationPolicy> > > single_exporters_; CommunicationPolicy communication_policy_; - // local storage for sending spikes + // local buffer for spikes std::vector<spike_type> local_spikes_; std::vector<spike_type> global_spikes_; }; - - } //communication } // namespace mc } // namespace nest