Skip to content
Snippets Groups Projects
Commit ae276099 authored by w.klijn's avatar w.klijn
Browse files

Got a working version with all stuff set in the miniapp. Needs to be refactored

parent 8ce9423a
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,7 @@
#include <iostream>
#include <fstream>
#include <memory>
#include <vector>
#include <json/src/json.hpp>
......@@ -16,6 +17,7 @@
#include <profiling/profiler.hpp>
#include <communication/communicator.hpp>
#include <communication/global_policy.hpp>
#include <communication/exporter_spike_file.hpp>
#include <util/ioutil.hpp>
#include <util/optional.hpp>
......@@ -29,12 +31,15 @@ using global_policy = communication::global_policy;
using lowered_cell = fvm::fvm_cell<double, cell_local_size_type>;
using model_type = model<lowered_cell>;
using sample_trace_type = sample_trace<model_type::time_type, model_type::value_type>;
using time_type = model_type::time_type;
using sample_trace_type = sample_trace<time_type, model_type::value_type>;
using file_export_type = communication::exporter_spike_file<time_type, global_policy>;
void banner();
std::unique_ptr<recipe> make_recipe(const io::cl_options&, const probe_distribution&);
std::unique_ptr<sample_trace_type> make_trace(cell_member_type probe_id, probe_spec probe);
std::pair<cell_gid_type, cell_gid_type> distribute_cells(cell_size_type ncells);
using communicator_type = communication::communicator<time_type, communication::global_policy>;
using spike_type = typename communicator_type::spike_type;
void write_trace_json(const sample_trace_type& trace, const std::string& prefix = "trace_");
......@@ -63,15 +68,35 @@ int main(int argc, char** argv) {
// build model from recipe
// TODO: I would rather just forward the options object.
model_type::file_output_parameters model_params(
options.spike_file_output,
options.single_file_per_rank,
options.over_write,
options.output_path,
options.file_name,
options.file_extention
);
model_type m(*recipe, cell_range.first, cell_range.second, model_params);
model_type m(*recipe, cell_range.first, cell_range.second);
std::unique_ptr<file_export_type> file_exporter;
if (!options.spike_file_output) {
m.set_global_spike_callback(
file_export_type::do_nothing);
m.set_local_spike_callback(
file_export_type::do_nothing);
}
else {
file_exporter = nest::mc::util::make_unique<file_export_type>(
options.file_name, options.output_path,
options.file_extention, true);
if (options.single_file_per_rank) {
m.set_global_spike_callback(
file_export_type::do_nothing);
m.set_local_spike_callback(
[&](const std::vector<spike_type>& spikes) { file_exporter->do_export(spikes); });
}
else {
m.set_global_spike_callback(
[&](const std::vector<spike_type>& spikes) { file_exporter->do_export(spikes); });
m.set_local_spike_callback(
file_export_type::do_nothing);
}
}
// inject some artificial spikes, 1 per 20 neurons.
cell_gid_type spike_cell = 20*((cell_range.first+19)/20);
......
#pragma once
#include <algorithm>
#include <iostream>
#include <vector>
#include <memory>
#include <utility>
#include <string>
#include <spike.hpp>
#include <util.hpp>
#include <common_types.hpp>
#include "exporter_interface.hpp"
#include "exporter_spike_file.hpp"
#include "exporter_spike_single_file.hpp"
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)
{
// simple switch to turn of the export, object will still be in a valid
// state.
if (!spike_file_output_) {
return;
}
// single file per rank exporters
if (single_file_per_rank) {
rank_exporters_.push_back(
nest::mc::util::make_unique<
nest::mc::communication::exporter_spike_file<Time, CommunicationPolicy> >(
file_name, output_path, file_extention, over_write));
}
// single file per simulation exporters
if (!single_file_per_rank) { // TODO: When we add more exporters and
//agreed on the parameter input this should be cleanup up.
if (communication_policy_.id() == 0) {
single_exporters_.push_back(
nest::mc::util::make_unique<
nest::mc::communication::exporter_spike_file<Time, CommunicationPolicy> >(
file_name, output_path, file_extention, over_write));
}
}
}
// Perform a export of local spikes, typically used for exporting to multi-
// ple files from each rank individually.
// spikes are buffer before export
void local_export_callback(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));
// 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 global_export_callback(const std::vector<spike_type>& spikes)
{
if (!spike_file_output_) {
return;
}
// We only output on a single rank
if (!communication_policy_.id() == 0) {
return;
}
global_spikes_.insert(std::end(global_spikes_),
std::begin(spikes), std::end(spikes));
// TODO: Do each exporter in a parallel thread?
for (auto &exporter : single_exporters_) {
exporter->do_export(spikes);
}
global_spikes_.clear();
}
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 buffer for spikes
std::vector<spike_type> local_spikes_;
std::vector<spike_type> global_spikes_;
};
} //communication
} // namespace mc
} // namespace nest
......@@ -26,6 +26,10 @@ public:
// Returns the status of the exporter
virtual bool good() const = 0;
// Static NULL version of the do_export function for NOP callbacks
static void do_nothing(const std::vector<spike_type>&)
{}
};
} //communication
......
......@@ -12,7 +12,6 @@
#include <thread_private_spike_store.hpp>
#include <communication/communicator.hpp>
#include <communication/global_policy.hpp>
#include <communication/export_manager.hpp>
#include <profiling/profiler.hpp>
#include "trace_sampler.hpp"
......@@ -23,47 +22,19 @@ namespace mc {
template <typename Cell>
class model {
public:
// TODO:We need to think how to transport parameters accros the different classes
// Move the io to src directory would make it allot easier!!
struct file_output_parameters
{
bool spike_file_output;
bool single_file_per_rank;
bool over_write;
std::string output_path;
std::string file_name;
std::string file_extention;
file_output_parameters(bool spike_file_output_i,
bool single_file_per_rank_i,
bool over_write_i,
std::string output_path_i,
std::string file_name_i,
std::string file_extention_i)
:
spike_file_output(spike_file_output_i),
single_file_per_rank(single_file_per_rank_i),
over_write(over_write_i),
output_path(output_path_i),
file_name(file_name_i),
file_extention(file_extention_i)
{}
};
using cell_group_type = cell_group<Cell>;
using time_type = typename cell_group_type::time_type;
using time_type = typename cell_group_type::time_type;
using value_type = typename cell_group_type::value_type;
using communicator_type = communication::communicator<time_type, communication::global_policy>;
using sampler_function = typename cell_group_type::sampler_function;
using spike_type = typename communicator_type::spike_type;
struct probe_record {
cell_member_type id;
probe_spec probe;
};
model(const recipe& rec, cell_gid_type cell_from, cell_gid_type cell_to,
file_output_parameters file_output_parameters_i):
model(const recipe& rec, cell_gid_type cell_from, cell_gid_type cell_to):
cell_from_(cell_from),
cell_to_(cell_to),
communicator_(cell_from, cell_to)
......@@ -99,14 +70,6 @@ public:
}
communicator_.construct();
exporter_ = nest::mc::util::make_unique<exporter_manager_type>(
file_output_parameters_i.spike_file_output,
file_output_parameters_i.single_file_per_rank,
file_output_parameters_i.over_write,
file_output_parameters_i.output_path,
file_output_parameters_i.file_name,
file_output_parameters_i.file_extention);
// Allocate an empty queue buffer for each cell group
// These must be set initially to ensure that a queue is available for each
// cell group for the first time step.
......@@ -144,7 +107,7 @@ public:
auto update_cells = [&] () {
threading::parallel_for::apply(
0u, cell_groups_.size(),
[&](unsigned i) {
[&](unsigned i) {
auto &group = cell_groups_[i];
PE("stepping","events");
......@@ -173,10 +136,10 @@ public:
auto exchange = [&] () {
PE("stepping", "exchange");
auto local_spikes = previous_spikes().gather();
exporter_->local_export_callback(local_spikes);
local_export_callback_(local_spikes);
future_events() = communicator_.exchange(local_spikes,
// send the exporter function as pointers to export
[&] (const std::vector<spike_type>& spikes){ exporter_->global_export_callback(spikes); });
// send the exporter function as pointer
[&] (const std::vector<spike_type>& spikes){ global_export_callback_(spikes); });
PL(2);
};
......@@ -215,6 +178,19 @@ public:
std::size_t num_spikes() const { return communicator_.num_spikes(); }
std::size_t num_groups() const { return cell_groups_.size(); }
void set_global_spike_callback(std::function<void(
const std::vector<spike_type>&)> global_export_callback)
{
global_export_callback_ = global_export_callback;
}
void set_local_spike_callback(std::function<void(
const std::vector<spike_type>&)> local_export_callback)
{
local_export_callback_ = local_export_callback;
}
private:
cell_gid_type cell_from_;
cell_gid_type cell_to_;
......@@ -222,7 +198,7 @@ private:
std::vector<cell_group_type> cell_groups_;
communicator_type communicator_;
std::vector<probe_record> probes_;
using spike_type = typename communicator_type::spike_type;
using event_queue_type = typename communicator_type::event_queue;
util::double_buffer< std::vector<event_queue_type> > event_queues_;
......@@ -230,8 +206,8 @@ private:
using local_spike_store_type = thread_private_spike_store<time_type>;
util::double_buffer< local_spike_store_type > local_spikes_;
using exporter_manager_type = nest::mc::communication::export_manager<time_type, communication::global_policy>;
std::unique_ptr<exporter_manager_type> exporter_;
std::function<void(const std::vector<spike_type>&)> global_export_callback_;
std::function<void(const std::vector<spike_type>&)> local_export_callback_;
// Convenience functions that map the spike buffers and event queues onto
// the appropriate integration interval.
//
......
......@@ -13,7 +13,7 @@
#include <communication/communicator.hpp>
#include <communication/global_policy.hpp>
#include <communication/export_manager.hpp>
#include <communication/exporter_spike_file.hpp>
#include <profiling/profiler.hpp>
using namespace nest::mc;
......@@ -74,8 +74,8 @@ int main(int argc, char** argv)
}
// Create the sut
communication::export_manager<time_type, global_policy> manager(
true, file_per_rank, true, "./", "spikes", "gdf");
communication::exporter_spike_file<time_type, global_policy> exporter(
"spikes", "./", "gdf", true);
// We need the nr of ranks to calculate the nr of spikes to produce per
// rank
......@@ -106,7 +106,7 @@ int main(int argc, char** argv)
for (auto idx = 0; idx < nr_repeats; ++idx) {
auto time_start = timer::tic();
manager.local_export_callback(spikes);
exporter.do_export(spikes);
auto run_time = timer::toc(time_start);
time_total += run_time;
timings_arr[idx] = run_time;
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment