From 8c056fb6da517299a07819bd539995c038e9e0b0 Mon Sep 17 00:00:00 2001 From: Jorge Blanco Alonso <41900536+jorblancoa@users.noreply.github.com> Date: Thu, 17 Nov 2022 14:46:08 +0100 Subject: [PATCH 1/6] Improve memory usage in report initialization (#882) * Use a vector for the report target gids in order to save memory * Add intersection function for the report gids * Clean up target vector after initialization * sync gids and compartment id types to sonata --- coreneuron/apps/main1.cpp | 8 +- .../io/reports/binary_report_handler.cpp | 13 +- .../io/reports/binary_report_handler.hpp | 11 +- coreneuron/io/reports/nrnreport.hpp | 2 +- .../reports/report_configuration_parser.cpp | 11 +- coreneuron/io/reports/report_event.hpp | 4 +- coreneuron/io/reports/report_handler.cpp | 232 +++++++++--------- coreneuron/io/reports/report_handler.hpp | 18 +- .../io/reports/sonata_report_handler.cpp | 15 +- .../io/reports/sonata_report_handler.hpp | 13 +- 10 files changed, 162 insertions(+), 165 deletions(-) diff --git a/coreneuron/apps/main1.cpp b/coreneuron/apps/main1.cpp index fb74df7d0..b36a245c9 100644 --- a/coreneuron/apps/main1.cpp +++ b/coreneuron/apps/main1.cpp @@ -428,13 +428,13 @@ static void trajectory_return() { } } -std::unique_ptr create_report_handler(ReportConfiguration& config, +std::unique_ptr create_report_handler(const ReportConfiguration& config, const SpikesInfo& spikes_info) { std::unique_ptr report_handler; if (config.format == "Bin") { - report_handler = std::make_unique(config); + report_handler = std::make_unique(); } else if (config.format == "SONATA") { - report_handler = std::make_unique(config, spikes_info); + report_handler = std::make_unique(spikes_info); } else { if (nrnmpi_myid == 0) { printf(" WARNING : Report name '%s' has unknown format: '%s'.\n", @@ -595,7 +595,7 @@ extern "C" int run_solve_core(int argc, char** argv) { std::unique_ptr report_handler = create_report_handler(configs[i], spikes_info); if (report_handler) { - report_handler->create_report(dt, tstop, delay); + report_handler->create_report(configs[i], dt, tstop, delay); report_handlers.push_back(std::move(report_handler)); } if (configs[i].report_dt < min_report_dt) { diff --git a/coreneuron/io/reports/binary_report_handler.cpp b/coreneuron/io/reports/binary_report_handler.cpp index 45369408a..00335476a 100644 --- a/coreneuron/io/reports/binary_report_handler.cpp +++ b/coreneuron/io/reports/binary_report_handler.cpp @@ -13,11 +13,14 @@ namespace coreneuron { -void BinaryReportHandler::create_report(double dt, double tstop, double delay) { +void BinaryReportHandler::create_report(ReportConfiguration& config, + double dt, + double tstop, + double delay) { #ifdef ENABLE_BIN_REPORTS records_set_atomic_step(dt); #endif // ENABLE_BIN_REPORTS - ReportHandler::create_report(dt, tstop, delay); + ReportHandler::create_report(config, dt, tstop, delay); } #ifdef ENABLE_BIN_REPORTS @@ -44,7 +47,7 @@ static void create_custom_extra(const CellMapping& mapping, std::array& } void BinaryReportHandler::register_section_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report, bool is_soma_target) { create_extra_func create_extra = is_soma_target ? create_soma_extra : create_compartment_extra; @@ -52,14 +55,14 @@ void BinaryReportHandler::register_section_report(const NrnThread& nt, } void BinaryReportHandler::register_custom_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report) { create_extra_func create_extra = create_custom_extra; register_report(nt, config, vars_to_report, create_extra); } void BinaryReportHandler::register_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report, create_extra_func& create_extra) { int sizemapping = 1; diff --git a/coreneuron/io/reports/binary_report_handler.hpp b/coreneuron/io/reports/binary_report_handler.hpp index 77c7cb676..8ae93bb61 100644 --- a/coreneuron/io/reports/binary_report_handler.hpp +++ b/coreneuron/io/reports/binary_report_handler.hpp @@ -20,23 +20,20 @@ namespace coreneuron { class BinaryReportHandler: public ReportHandler { public: - BinaryReportHandler(ReportConfiguration& config) - : ReportHandler(config) {} - - void create_report(double dt, double tstop, double delay) override; + void create_report(ReportConfiguration& config, double dt, double tstop, double delay) override; #ifdef ENABLE_BIN_REPORTS void register_section_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report, bool is_soma_target) override; void register_custom_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report) override; private: using create_extra_func = std::function&)>; void register_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report, create_extra_func& create_extra); #endif // ENABLE_BIN_REPORTS diff --git a/coreneuron/io/reports/nrnreport.hpp b/coreneuron/io/reports/nrnreport.hpp index 7cdc05806..acc60fa21 100644 --- a/coreneuron/io/reports/nrnreport.hpp +++ b/coreneuron/io/reports/nrnreport.hpp @@ -101,7 +101,7 @@ struct ReportConfiguration { double stop; // stop time of report int num_gids; // total number of gids int buffer_size; // hint on buffer size used for this report - std::set target; // list of gids for this report + std::vector target; // list of gids for this report }; void setup_report_engine(double dt_report, double mindelay); diff --git a/coreneuron/io/reports/report_configuration_parser.cpp b/coreneuron/io/reports/report_configuration_parser.cpp index 6c69662b7..29ca0b564 100644 --- a/coreneuron/io/reports/report_configuration_parser.cpp +++ b/coreneuron/io/reports/report_configuration_parser.cpp @@ -106,15 +106,14 @@ void register_target_type(ReportConfiguration& report, ReportType report_type) { std::vector create_report_configurations(const std::string& conf_file, const std::string& output_dir, SpikesInfo& spikes_info) { - std::vector reports; std::string report_on; int target; std::ifstream report_conf(conf_file); int num_reports = 0; report_conf >> num_reports; - for (int i = 0; i < num_reports; i++) { - ReportConfiguration report; + std::vector reports(num_reports); + for (auto& report: reports) { report.buffer_size = 4; // default size to 4 Mb report_conf >> report.name >> report.target_name >> report.type_str >> report_on >> @@ -147,15 +146,13 @@ std::vector create_report_configurations(const std::string& parse_filter_string(report_on, report); } if (report.num_gids) { - std::vector new_gids(report.num_gids); + report.target.resize(report.num_gids); report_conf.ignore(std::numeric_limits::max(), '\n'); - report_conf.read(reinterpret_cast(new_gids.data()), + report_conf.read(reinterpret_cast(report.target.data()), report.num_gids * sizeof(int)); - report.target = std::set(new_gids.begin(), new_gids.end()); // extra new line: skip report_conf.ignore(std::numeric_limits::max(), '\n'); } - reports.push_back(report); } // read population information for spike report int num_populations; diff --git a/coreneuron/io/reports/report_event.hpp b/coreneuron/io/reports/report_event.hpp index 20d325614..fb9cf5fef 100644 --- a/coreneuron/io/reports/report_event.hpp +++ b/coreneuron/io/reports/report_event.hpp @@ -20,7 +20,7 @@ namespace coreneuron { #if defined(ENABLE_BIN_REPORTS) || defined(ENABLE_SONATA_REPORTS) struct VarWithMapping { - int id; + uint32_t id; double* var_value; VarWithMapping(int id_, double* v_) : id(id_) @@ -28,7 +28,7 @@ struct VarWithMapping { }; // mapping the set of variables pointers to report to its gid -using VarsToReport = std::unordered_map>; +using VarsToReport = std::unordered_map>; class ReportEvent: public DiscreteEvent { public: diff --git a/coreneuron/io/reports/report_handler.cpp b/coreneuron/io/reports/report_handler.cpp index 84341e7a4..3a1bd5aae 100644 --- a/coreneuron/io/reports/report_handler.cpp +++ b/coreneuron/io/reports/report_handler.cpp @@ -13,18 +13,41 @@ namespace coreneuron { -void ReportHandler::create_report(double dt, double tstop, double delay) { +template +std::vector intersection_gids(const NrnThread& nt, std::vector& target_gids) { + std::vector thread_gids; + for (int i = 0; i < nt.ncell; i++) { + thread_gids.push_back(nt.presyns[i].gid_); + } + std::vector intersection; + + std::sort(thread_gids.begin(), thread_gids.end()); + std::sort(target_gids.begin(), target_gids.end()); + + std::set_intersection(thread_gids.begin(), + thread_gids.end(), + target_gids.begin(), + target_gids.end(), + back_inserter(intersection)); + + return intersection; +} + +void ReportHandler::create_report(ReportConfiguration& report_config, + double dt, + double tstop, + double delay) { #if defined(ENABLE_BIN_REPORTS) || defined(ENABLE_SONATA_REPORTS) - if (m_report_config.start < t) { - m_report_config.start = t; + if (report_config.start < t) { + report_config.start = t; } - m_report_config.stop = std::min(m_report_config.stop, tstop); + report_config.stop = std::min(report_config.stop, tstop); - for (const auto& mech: m_report_config.mech_names) { - m_report_config.mech_ids.emplace_back(nrn_get_mechtype(mech.data())); + for (const auto& mech: report_config.mech_names) { + report_config.mech_ids.emplace_back(nrn_get_mechtype(mech.data())); } - if (m_report_config.type == SynapseReport && m_report_config.mech_ids.empty()) { - std::cerr << "[ERROR] mechanism to report: " << m_report_config.mech_names[0] + if (report_config.type == SynapseReport && report_config.mech_ids.empty()) { + std::cerr << "[ERROR] mechanism to report: " << report_config.mech_names[0] << " is not mapped in this simulation, cannot report on it \n"; nrn_abort(1); } @@ -35,39 +58,35 @@ void ReportHandler::create_report(double dt, double tstop, double delay) { continue; } const std::vector& nodes_to_gid = map_gids(nt); + const std::vector gids_to_report = intersection_gids(nt, report_config.target); VarsToReport vars_to_report; bool is_soma_target; - switch (m_report_config.type) { + switch (report_config.type) { case IMembraneReport: report_variable = nt.nrn_fast_imem->nrn_sav_rhs; case SectionReport: - vars_to_report = - get_section_vars_to_report(nt, - m_report_config.target, - report_variable, - m_report_config.section_type, - m_report_config.section_all_compartments); - is_soma_target = m_report_config.section_type == SectionType::Soma || - m_report_config.section_type == SectionType::Cell; - register_section_report(nt, m_report_config, vars_to_report, is_soma_target); + vars_to_report = get_section_vars_to_report(nt, + gids_to_report, + report_variable, + report_config.section_type, + report_config.section_all_compartments); + is_soma_target = report_config.section_type == SectionType::Soma || + report_config.section_type == SectionType::Cell; + register_section_report(nt, report_config, vars_to_report, is_soma_target); break; case SummationReport: - vars_to_report = get_summation_vars_to_report(nt, - m_report_config.target, - m_report_config, - nodes_to_gid); - register_custom_report(nt, m_report_config, vars_to_report); + vars_to_report = + get_summation_vars_to_report(nt, gids_to_report, report_config, nodes_to_gid); + register_custom_report(nt, report_config, vars_to_report); break; default: - vars_to_report = get_synapse_vars_to_report(nt, m_report_config, nodes_to_gid); - register_custom_report(nt, m_report_config, vars_to_report); + vars_to_report = + get_synapse_vars_to_report(nt, gids_to_report, report_config, nodes_to_gid); + register_custom_report(nt, report_config, vars_to_report); } if (!vars_to_report.empty()) { - auto report_event = std::make_unique(dt, - t, - vars_to_report, - m_report_config.output_path.data(), - m_report_config.report_dt); + auto report_event = std::make_unique( + dt, t, vars_to_report, report_config.output_path.data(), report_config.report_dt); report_event->send(t, net_cvode_instance, &nt); m_report_events.push_back(std::move(report_event)); } @@ -82,7 +101,7 @@ void ReportHandler::create_report(double dt, double tstop, double delay) { #if defined(ENABLE_BIN_REPORTS) || defined(ENABLE_SONATA_REPORTS) void ReportHandler::register_section_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report, bool is_soma_target) { if (nrnmpi_myid == 0) { @@ -91,7 +110,7 @@ void ReportHandler::register_section_report(const NrnThread& nt, } } void ReportHandler::register_custom_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report) { if (nrnmpi_myid == 0) { std::cerr << "[WARNING] : Format '" << config.format << "' in report '" @@ -145,7 +164,7 @@ void register_sections_to_report(const SecMapping* sections, } VarsToReport ReportHandler::get_section_vars_to_report(const NrnThread& nt, - const std::set& target, + const std::vector& gids_to_report, double* report_variable, SectionType section_type, bool all_compartments) const { @@ -158,47 +177,38 @@ VarsToReport ReportHandler::get_section_vars_to_report(const NrnThread& nt, nrn_abort(1); } - for (int i = 0; i < nt.ncell; i++) { - int gid = nt.presyns[i].gid_; - if (target.find(gid) != target.end()) { - const auto& cell_mapping = mapinfo->get_cell_mapping(gid); - if (cell_mapping == nullptr) { - std::cerr - << "[COMPARTMENTS] Error : Compartment mapping information is missing for gid " - << gid << '\n'; - nrn_abort(1); - } - std::vector to_report; - to_report.reserve(cell_mapping->size()); + for (const auto& gid: gids_to_report) { + const auto& cell_mapping = mapinfo->get_cell_mapping(gid); + if (cell_mapping == nullptr) { + std::cerr + << "[COMPARTMENTS] Error : Compartment mapping information is missing for gid " + << gid << '\n'; + nrn_abort(1); + } + std::vector to_report; + to_report.reserve(cell_mapping->size()); - if (section_type_str == "All") { - const auto& section_mapping = cell_mapping->secmapvec; - for (const auto& sections: section_mapping) { - register_sections_to_report(sections, - to_report, - report_variable, - all_compartments); - } - } else { - /** get section list mapping for the type, if available */ - if (cell_mapping->get_seclist_section_count(section_type_str) > 0) { - const auto& sections = cell_mapping->get_seclist_mapping(section_type_str); - register_sections_to_report(sections, - to_report, - report_variable, - all_compartments); - } + if (section_type_str == "All") { + const auto& section_mapping = cell_mapping->secmapvec; + for (const auto& sections: section_mapping) { + register_sections_to_report(sections, to_report, report_variable, all_compartments); + } + } else { + /** get section list mapping for the type, if available */ + if (cell_mapping->get_seclist_section_count(section_type_str) > 0) { + const auto& sections = cell_mapping->get_seclist_mapping(section_type_str); + register_sections_to_report(sections, to_report, report_variable, all_compartments); } - vars_to_report[gid] = to_report; } + vars_to_report[gid] = to_report; } return vars_to_report; } VarsToReport ReportHandler::get_summation_vars_to_report( const NrnThread& nt, - const std::set& target, - ReportConfiguration& report, + const std::vector& gids_to_report, + const ReportConfiguration& report, const std::vector& nodes_to_gids) const { VarsToReport vars_to_report; const auto* mapinfo = static_cast(nt.mapping); @@ -209,11 +219,7 @@ VarsToReport ReportHandler::get_summation_vars_to_report( nrn_abort(1); } - for (int i = 0; i < nt.ncell; i++) { - int gid = nt.presyns[i].gid_; - if (report.target.find(gid) == report.target.end()) { - continue; - } + for (const auto& gid: gids_to_report) { bool has_imembrane = false; // In case we need convertion of units int scale = 1; @@ -244,65 +250,59 @@ VarsToReport ReportHandler::get_summation_vars_to_report( has_imembrane = true; } } - if (target.find(gid) != target.end()) { - const auto& cell_mapping = mapinfo->get_cell_mapping(gid); - if (cell_mapping == nullptr) { - std::cerr - << "[SUMMATION] Error : Compartment mapping information is missing for gid " - << gid << '\n'; - nrn_abort(1); - } - std::vector to_report; - to_report.reserve(cell_mapping->size()); - summation_report.summation_.resize(nt.end); - double* report_variable = summation_report.summation_.data(); - const auto& section_type_str = getSectionTypeStr(report.section_type); - if (report.section_type != SectionType::All) { - if (cell_mapping->get_seclist_section_count(section_type_str) > 0) { - const auto& sections = cell_mapping->get_seclist_mapping(section_type_str); - register_sections_to_report(sections, - to_report, - report_variable, - report.section_all_compartments); - } + const auto& cell_mapping = mapinfo->get_cell_mapping(gid); + if (cell_mapping == nullptr) { + std::cerr << "[SUMMATION] Error : Compartment mapping information is missing for gid " + << gid << '\n'; + nrn_abort(1); + } + std::vector to_report; + to_report.reserve(cell_mapping->size()); + summation_report.summation_.resize(nt.end); + double* report_variable = summation_report.summation_.data(); + const auto& section_type_str = getSectionTypeStr(report.section_type); + if (report.section_type != SectionType::All) { + if (cell_mapping->get_seclist_section_count(section_type_str) > 0) { + const auto& sections = cell_mapping->get_seclist_mapping(section_type_str); + register_sections_to_report(sections, + to_report, + report_variable, + report.section_all_compartments); } - const auto& section_mapping = cell_mapping->secmapvec; - for (const auto& sections: section_mapping) { - for (auto& section: sections->secmap) { - // compartment_id - int section_id = section.first; - auto& segment_ids = section.second; - for (const auto& segment_id: segment_ids) { - // corresponding voltage in coreneuron voltage array - if (has_imembrane) { - summation_report.currents_[segment_id].push_back( - std::make_pair(nt.nrn_fast_imem->nrn_sav_rhs + segment_id, 1)); - } - if (report.section_type == SectionType::All) { - double* variable = report_variable + segment_id; - to_report.emplace_back(VarWithMapping(section_id, variable)); - } else if (report.section_type == SectionType::Cell) { - summation_report.gid_segments_[gid].push_back(segment_id); - } + } + const auto& section_mapping = cell_mapping->secmapvec; + for (const auto& sections: section_mapping) { + for (auto& section: sections->secmap) { + // compartment_id + int section_id = section.first; + auto& segment_ids = section.second; + for (const auto& segment_id: segment_ids) { + // corresponding voltage in coreneuron voltage array + if (has_imembrane) { + summation_report.currents_[segment_id].push_back( + std::make_pair(nt.nrn_fast_imem->nrn_sav_rhs + segment_id, 1)); + } + if (report.section_type == SectionType::All) { + double* variable = report_variable + segment_id; + to_report.emplace_back(VarWithMapping(section_id, variable)); + } else if (report.section_type == SectionType::Cell) { + summation_report.gid_segments_[gid].push_back(segment_id); } } } - vars_to_report[gid] = to_report; } + vars_to_report[gid] = to_report; } return vars_to_report; } VarsToReport ReportHandler::get_synapse_vars_to_report( const NrnThread& nt, - ReportConfiguration& report, + const std::vector& gids_to_report, + const ReportConfiguration& report, const std::vector& nodes_to_gids) const { VarsToReport vars_to_report; - for (int i = 0; i < nt.ncell; i++) { - int gid = nt.presyns[i].gid_; - if (report.target.find(gid) == report.target.end()) { - continue; - } + for (const auto& gid: gids_to_report) { // There can only be 1 mechanism nrn_assert(report.mech_ids.size() == 1); auto mech_id = report.mech_ids[0]; diff --git a/coreneuron/io/reports/report_handler.hpp b/coreneuron/io/reports/report_handler.hpp index 084886c96..1954c947b 100644 --- a/coreneuron/io/reports/report_handler.hpp +++ b/coreneuron/io/reports/report_handler.hpp @@ -19,35 +19,33 @@ namespace coreneuron { class ReportHandler { public: - ReportHandler(ReportConfiguration& config) - : m_report_config(config){}; virtual ~ReportHandler() = default; - virtual void create_report(double dt, double tstop, double delay); + virtual void create_report(ReportConfiguration& config, double dt, double tstop, double delay); #if defined(ENABLE_BIN_REPORTS) || defined(ENABLE_SONATA_REPORTS) virtual void register_section_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report, bool is_soma_target); virtual void register_custom_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report); VarsToReport get_section_vars_to_report(const NrnThread& nt, - const std::set& target, + const std::vector& gids_to_report, double* report_variable, SectionType section_type, bool all_compartments) const; VarsToReport get_summation_vars_to_report(const NrnThread& nt, - const std::set& target, - ReportConfiguration& report, + const std::vector& gids_to_report, + const ReportConfiguration& report, const std::vector& nodes_to_gids) const; VarsToReport get_synapse_vars_to_report(const NrnThread& nt, - ReportConfiguration& report, + const std::vector& gids_to_report, + const ReportConfiguration& report, const std::vector& nodes_to_gids) const; std::vector map_gids(const NrnThread& nt) const; #endif // defined(ENABLE_BIN_REPORTS) || defined(ENABLE_SONATA_REPORTS) protected: - ReportConfiguration m_report_config; #if defined(ENABLE_BIN_REPORTS) || defined(ENABLE_SONATA_REPORTS) std::vector> m_report_events; #endif // defined(ENABLE_BIN_REPORTS) || defined(ENABLE_SONATA_REPORTS) diff --git a/coreneuron/io/reports/sonata_report_handler.cpp b/coreneuron/io/reports/sonata_report_handler.cpp index 99f5709d5..3aaf18361 100644 --- a/coreneuron/io/reports/sonata_report_handler.cpp +++ b/coreneuron/io/reports/sonata_report_handler.cpp @@ -17,23 +17,26 @@ namespace coreneuron { -void SonataReportHandler::create_report(double dt, double tstop, double delay) { +void SonataReportHandler::create_report(ReportConfiguration& config, + double dt, + double tstop, + double delay) { #ifdef ENABLE_SONATA_REPORTS sonata_set_atomic_step(dt); #endif // ENABLE_SONATA_REPORTS - ReportHandler::create_report(dt, tstop, delay); + ReportHandler::create_report(config, dt, tstop, delay); } #ifdef ENABLE_SONATA_REPORTS void SonataReportHandler::register_section_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report, bool is_soma_target) { register_report(nt, config, vars_to_report); } void SonataReportHandler::register_custom_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report) { register_report(nt, config, vars_to_report); } @@ -55,7 +58,7 @@ std::pair SonataReportHandler::get_population_info(int gid) { } void SonataReportHandler::register_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report) { sonata_create_report(config.output_path.data(), config.start, @@ -66,7 +69,7 @@ void SonataReportHandler::register_report(const NrnThread& nt, sonata_set_report_max_buffer_size_hint(config.output_path.data(), config.buffer_size); for (const auto& kv: vars_to_report) { - int gid = kv.first; + uint64_t gid = kv.first; const std::vector& vars = kv.second; if (!vars.size()) continue; diff --git a/coreneuron/io/reports/sonata_report_handler.hpp b/coreneuron/io/reports/sonata_report_handler.hpp index 0d8957b91..e0a60103d 100644 --- a/coreneuron/io/reports/sonata_report_handler.hpp +++ b/coreneuron/io/reports/sonata_report_handler.hpp @@ -17,23 +17,22 @@ namespace coreneuron { class SonataReportHandler: public ReportHandler { public: - SonataReportHandler(ReportConfiguration& config, const SpikesInfo& spikes_info) - : ReportHandler(config) - , m_spikes_info(spikes_info) {} + SonataReportHandler(const SpikesInfo& spikes_info) + : m_spikes_info(spikes_info) {} - void create_report(double dt, double tstop, double delay) override; + void create_report(ReportConfiguration& config, double dt, double tstop, double delay) override; #ifdef ENABLE_SONATA_REPORTS void register_section_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report, bool is_soma_target) override; void register_custom_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report) override; private: void register_report(const NrnThread& nt, - ReportConfiguration& config, + const ReportConfiguration& config, const VarsToReport& vars_to_report); std::pair get_population_info(int gid); #endif // ENABLE_SONATA_REPORTS From a3ae3cd422933b6e43bbca80a978a3896d20ee8a Mon Sep 17 00:00:00 2001 From: Ioannis Magkanaris Date: Thu, 30 Jun 2022 08:27:40 +0200 Subject: [PATCH 2/6] Print memory footprint of each mechanism (#833) * Print each mechanism's size * Fix compilation with -DDEBUG * Improve the calculation of the total memory for each mechanism * Improved calculation of NrnThreadMembList Co-authored-by: Olli Lupton --- README.md | 2 +- coreneuron/apps/corenrn_parameters.cpp | 2 +- coreneuron/apps/corenrn_parameters.hpp | 8 +++++- coreneuron/io/mech_report.cpp | 22 ++++++++++++---- coreneuron/io/nrn_setup.cpp | 36 +++++++++++++++++++++++--- coreneuron/io/nrn_setup.hpp | 2 ++ coreneuron/mechanism/mechanism.hpp | 14 ++++++++++ 7 files changed, 74 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a2dc9b661..473f0349b 100644 --- a/README.md +++ b/README.md @@ -395,4 +395,4 @@ You can see current [contributors here](https://github.com/BlueBrain/CoreNeuron/ CoreNEURON is developed in a joint collaboration between the Blue Brain Project and Yale University. This work is supported by funding to the Blue Brain Project, a research center of the École polytechnique fédérale de Lausanne (EPFL), from the Swiss government’s ETH Board of the Swiss Federal Institutes of Technology, NIH grant number R01NS11613 (Yale University), the European Union Seventh Framework Program (FP7/20072013) under grant agreement n◦ 604102 (HBP) and the European Union’s Horizon 2020 Framework Programme for Research and Innovation under Specific Grant Agreement n◦ 720270 (Human Brain Project SGA1), n◦ 785907 (Human Brain Project SGA2) and n◦ 945539 (Human Brain Project SGA3). -Copyright (c) 2016 - 2021 Blue Brain Project/EPFL +Copyright (c) 2016 - 2022 Blue Brain Project/EPFL diff --git a/coreneuron/apps/corenrn_parameters.cpp b/coreneuron/apps/corenrn_parameters.cpp index 9ec7270b7..40c322b18 100644 --- a/coreneuron/apps/corenrn_parameters.cpp +++ b/coreneuron/apps/corenrn_parameters.cpp @@ -40,7 +40,7 @@ corenrn_parameters::corenrn_parameters() { app.add_set( "--verbose", this->verbose, - {verbose_level::NONE, verbose_level::ERROR, verbose_level::INFO, verbose_level::DEBUG}, + {verbose_level::NONE, verbose_level::ERROR, verbose_level::INFO, verbose_level::DEBUG_INFO}, "Verbose level: 0 = NONE, 1 = ERROR, 2 = INFO, 3 = DEBUG. Default is INFO"); app.add_flag("--model-stats", this->model_stats, diff --git a/coreneuron/apps/corenrn_parameters.hpp b/coreneuron/apps/corenrn_parameters.hpp index cdf56f4ec..bfe646622 100644 --- a/coreneuron/apps/corenrn_parameters.hpp +++ b/coreneuron/apps/corenrn_parameters.hpp @@ -35,7 +35,13 @@ namespace coreneuron { struct corenrn_parameters_data { - enum verbose_level : std::uint32_t { NONE = 0, ERROR = 1, INFO = 2, DEBUG = 3, DEFAULT = INFO }; + enum verbose_level : std::uint32_t { + NONE = 0, + ERROR = 1, + INFO = 2, + DEBUG_INFO = 3, + DEFAULT = INFO + }; static constexpr int report_buff_size_default = 4; diff --git a/coreneuron/io/mech_report.cpp b/coreneuron/io/mech_report.cpp index aed2db634..872fb26a8 100644 --- a/coreneuron/io/mech_report.cpp +++ b/coreneuron/io/mech_report.cpp @@ -10,6 +10,7 @@ #include #include "coreneuron/coreneuron.hpp" +#include "coreneuron/io/nrn_setup.hpp" #include "coreneuron/mpi/nrnmpi.h" #include "coreneuron/apps/corenrn_parameters.hpp" @@ -19,6 +20,7 @@ void write_mech_report() { /// mechanim count across all gids, local to rank const auto n_memb_func = corenrn.get_memb_funcs().size(); std::vector local_mech_count(n_memb_func, 0); + std::vector local_mech_size(n_memb_func, 0); /// each gid record goes on separate row, only check non-empty threads for (int i = 0; i < nrn_nthread; i++) { @@ -27,10 +29,12 @@ void write_mech_report() { const int type = tml->index; const auto& ml = tml->ml; local_mech_count[type] += ml->nodecount; + local_mech_size[type] = memb_list_size(tml, true); } } std::vector total_mech_count(n_memb_func); + std::vector total_mech_size(n_memb_func); #if NRNMPI if (corenrn_param.mpi_enable) { @@ -39,21 +43,29 @@ void write_mech_report() { &total_mech_count[0], local_mech_count.size(), 1); - + nrnmpi_long_allreduce_vec(&local_mech_size[0], + &total_mech_size[0], + local_mech_size.size(), + 1); } else #endif { total_mech_count = local_mech_count; + total_mech_size = local_mech_size; } /// print global stats to stdout if (nrnmpi_myid == 0) { - printf("\n================ MECHANISMS COUNT BY TYPE ==================\n"); - printf("%4s %20s %10s\n", "Id", "Name", "Count"); + printf("\n================= MECHANISMS COUNT BY TYPE ===================\n"); + printf("%4s %20s %10s %25s\n", "Id", "Name", "Count", "Total memory size (KiB)"); for (size_t i = 0; i < total_mech_count.size(); i++) { - printf("%4lu %20s %10ld\n", i, nrn_get_mechname(i), total_mech_count[i]); + printf("%4lu %20s %10ld %25.2lf\n", + i, + nrn_get_mechname(i), + total_mech_count[i], + static_cast(total_mech_size[i]) / 1024); } - printf("=============================================================\n"); + printf("==============================================================\n"); } } diff --git a/coreneuron/io/nrn_setup.cpp b/coreneuron/io/nrn_setup.cpp index 5be6f96b0..6d798f75c 100644 --- a/coreneuron/io/nrn_setup.cpp +++ b/coreneuron/io/nrn_setup.cpp @@ -966,9 +966,37 @@ void read_phase3(NrnThread& nt, UserParams& userParams) { nt.summation_report_handler_ = std::make_unique(); } -static size_t memb_list_size(NrnThreadMembList* tml) { +/* Returns the size of the dynamically allocated memory for NrnThreadMembList + * Includes: + * - Size of NrnThreadMembList + * - Size of Memb_list + * - Size of nodeindices + * - Size of _permute + * - Size of _thread + * - Size of NetReceive and NetSend Buffers + * - Size of int variables + * - Size of double variables (If include_data is enabled. Those variables are already counted + * since they point to nt->_data.) + */ +size_t memb_list_size(NrnThreadMembList* tml, bool include_data) { size_t nbyte = sizeof(NrnThreadMembList) + sizeof(Memb_list); nbyte += tml->ml->nodecount * sizeof(int); + if (tml->ml->_permute) { + nbyte += tml->ml->nodecount * sizeof(int); + } + if (tml->ml->_thread) { + Memb_func& mf = corenrn.get_memb_func(tml->index); + nbyte += mf.thread_size_ * sizeof(ThreadDatum); + } + if (tml->ml->_net_receive_buffer) { + nbyte += sizeof(NetReceiveBuffer_t) + tml->ml->_net_receive_buffer->size_of_object(); + } + if (tml->ml->_net_send_buffer) { + nbyte += sizeof(NetSendBuffer_t) + tml->ml->_net_send_buffer->size_of_object(); + } + if (include_data) { + nbyte += corenrn.get_prop_param_size()[tml->index] * tml->ml->nodecount * sizeof(double); + } nbyte += corenrn.get_prop_dparam_size()[tml->index] * tml->ml->nodecount * sizeof(Datum); #ifdef DEBUG int i = tml->index; @@ -991,7 +1019,7 @@ size_t output_presyn_size(void) { size_t nbyte = sizeof(gid2out) + sizeof(int) * gid2out.size() + sizeof(PreSyn*) * gid2out.size(); #ifdef DEBUG - printf(" gid2out table bytes=~%ld size=%d\n", nbyte, gid2out.size()); + printf(" gid2out table bytes=~%ld size=%ld\n", nbyte, gid2out.size()); #endif return nbyte; } @@ -1003,7 +1031,7 @@ size_t input_presyn_size(void) { size_t nbyte = sizeof(gid2in) + sizeof(int) * gid2in.size() + sizeof(InputPreSyn*) * gid2in.size(); #ifdef DEBUG - printf(" gid2in table bytes=~%ld size=%d\n", nbyte, gid2in.size()); + printf(" gid2in table bytes=~%ld size=%ld\n", nbyte, gid2in.size()); #endif return nbyte; } @@ -1031,7 +1059,7 @@ size_t model_size(bool detailed_report) { // Memb_list size int nmech = 0; for (auto tml = nt.tml; tml; tml = tml->next) { - nb_nt += memb_list_size(tml); + nb_nt += memb_list_size(tml, false); ++nmech; } diff --git a/coreneuron/io/nrn_setup.hpp b/coreneuron/io/nrn_setup.hpp index 8d1f757b5..389b90c15 100644 --- a/coreneuron/io/nrn_setup.hpp +++ b/coreneuron/io/nrn_setup.hpp @@ -42,6 +42,8 @@ extern void nrn_setup_cleanup(); extern int nrn_i_layout(int i, int cnt, int j, int size, int layout); +size_t memb_list_size(NrnThreadMembList* tml, bool include_data); + size_t model_size(bool detailed_report); namespace coreneuron { diff --git a/coreneuron/mechanism/mechanism.hpp b/coreneuron/mechanism/mechanism.hpp index 65d7b29ce..ab78ad502 100644 --- a/coreneuron/mechanism/mechanism.hpp +++ b/coreneuron/mechanism/mechanism.hpp @@ -50,6 +50,13 @@ struct NetReceiveBuffer_t { int _displ_cnt; /* number of unique _pnt_index */ int _size; /* capacity */ int _pnt_offset; + size_t size_of_object() { + size_t nbytes = 0; + nbytes += _size * sizeof(int) * 3; + nbytes += (_size + 1) * sizeof(int); + nbytes += _size * sizeof(double) * 2; + return nbytes; + } }; struct NetSendBuffer_t: MemoryManaged { @@ -78,6 +85,13 @@ struct NetSendBuffer_t: MemoryManaged { _nsb_flag = (double*) ecalloc_align(_size, sizeof(double)); } + size_t size_of_object() { + size_t nbytes = 0; + nbytes += _size * sizeof(int) * 4; + nbytes += _size * sizeof(double) * 2; + return nbytes; + } + ~NetSendBuffer_t() { free_memory(_sendtype); free_memory(_vdata_index); From d3f8ebe9340a0cff345bd69d709d355575b93a7b Mon Sep 17 00:00:00 2001 From: Ioannis Magkanaris Date: Mon, 3 Oct 2022 14:25:24 +0200 Subject: [PATCH 3/6] Print mechanism count and memory size only if count is >0 (#864) --- coreneuron/io/mech_report.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/coreneuron/io/mech_report.cpp b/coreneuron/io/mech_report.cpp index 872fb26a8..715e13aef 100644 --- a/coreneuron/io/mech_report.cpp +++ b/coreneuron/io/mech_report.cpp @@ -56,14 +56,16 @@ void write_mech_report() { /// print global stats to stdout if (nrnmpi_myid == 0) { - printf("\n================= MECHANISMS COUNT BY TYPE ===================\n"); + printf("\n============== MECHANISMS COUNT AND SIZE BY TYPE =============\n"); printf("%4s %20s %10s %25s\n", "Id", "Name", "Count", "Total memory size (KiB)"); for (size_t i = 0; i < total_mech_count.size(); i++) { - printf("%4lu %20s %10ld %25.2lf\n", - i, - nrn_get_mechname(i), - total_mech_count[i], - static_cast(total_mech_size[i]) / 1024); + if (total_mech_count[i] > 0) { + printf("%4lu %20s %10ld %25.2lf\n", + i, + nrn_get_mechname(i), + total_mech_count[i], + static_cast(total_mech_size[i]) / 1024); + } } printf("==============================================================\n"); } From 149572c4a3ec929465719ea8249679edeb2dacac Mon Sep 17 00:00:00 2001 From: Pramod Kumbhar Date: Thu, 17 Nov 2022 22:56:10 +0100 Subject: [PATCH 4/6] Update nmodl find_package logic Update nmodl to new branch which could be 8.2 --- CMake/packages/Findnmodl.cmake | 2 +- external/nmodl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMake/packages/Findnmodl.cmake b/CMake/packages/Findnmodl.cmake index b7b73fdbb..222610ca2 100644 --- a/CMake/packages/Findnmodl.cmake +++ b/CMake/packages/Findnmodl.cmake @@ -32,7 +32,7 @@ find_program(nmodl_BINARY NAMES nmodl${CMAKE_EXECUTABLE_SUFFIX} HINTS "${CORENRN_NMODL_DIR}/bin" QUIET) -find_path(nmodl_INCLUDE "nmodl/fast_math.ispc" HINTS "${CORENRN_NMODL_DIR}/include") +find_path(nmodl_INCLUDE "nmodl/fast_math.hpp" HINTS "${CORENRN_NMODL_DIR}/include") find_path(nmodl_PYTHONPATH "nmodl/__init__.py" HINTS "${CORENRN_NMODL_DIR}/lib") # Checks 'REQUIRED', 'QUIET' and versions. diff --git a/external/nmodl b/external/nmodl index d38eb74b7..d996a004b 160000 --- a/external/nmodl +++ b/external/nmodl @@ -1 +1 @@ -Subproject commit d38eb74b71728e9ab3e9dc43c986d662faa3ff9e +Subproject commit d996a004b717af54d83996d36619698d613bd179 From 434d3a13d77be240f4541bb7127eb431a3fb4cda Mon Sep 17 00:00:00 2001 From: Pramod Kumbhar Date: Thu, 17 Nov 2022 23:12:46 +0100 Subject: [PATCH 5/6] upgrade python 3.6 to 3.7 --- .github/workflows/coreneuron-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coreneuron-ci.yml b/.github/workflows/coreneuron-ci.yml index 4dfdd5e1b..4a8e3a680 100644 --- a/.github/workflows/coreneuron-ci.yml +++ b/.github/workflows/coreneuron-ci.yml @@ -36,9 +36,9 @@ jobs: - {cmake_option: "-DCORENRN_ENABLE_MPI_DYNAMIC=ON", flag_warnings: ON} - {cmake_option: "-DCORENRN_ENABLE_MPI_DYNAMIC=ON -DCORENRN_ENABLE_SHARED=OFF"} - {cmake_option: "-DCORENRN_ENABLE_MPI=OFF"} - - {use_nmodl: ON, py_version: 3.6.7} + - {use_nmodl: ON, py_version: 3.7} - {use_nmodl: ON} - - {use_ispc: ON, py_version: 3.6.7} + - {use_ispc: ON, py_version: 3.7} include: - os: ubuntu-20.04 config: From c0fef44bc95939d63d0aecea9ef10135cd4c842e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandru=20S=C4=83vulescu?= Date: Mon, 14 Nov 2022 13:37:38 +0100 Subject: [PATCH 6/6] NRN submodule CI fixes (#883) * Ubuntu: * install pytest(cov) via pip * macOS * SDK_ROOT env * use gcc wrapper --- .github/workflows/test-as-submodule.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-as-submodule.yml b/.github/workflows/test-as-submodule.yml index 625a56609..a03155a55 100644 --- a/.github/workflows/test-as-submodule.yml +++ b/.github/workflows/test-as-submodule.yml @@ -28,6 +28,8 @@ jobs: fail-fast: false env: CMAKE_BUILD_PARALLEL_LEVEL: ${{matrix.cores}} + SDK_ROOT: $(xcrun --sdk macosx --show-sdk-path) + steps: - name: Install homebrew packages @@ -36,16 +38,16 @@ jobs: brew install bison coreutils flex ninja openmpi python3 -m pip install --upgrade numpy pytest pytest-cov echo /usr/local/opt/flex/bin:/usr/local/opt/bison/bin >> $GITHUB_PATH - echo "CC=clang" >> $GITHUB_ENV - echo "CXX=clang++" >> $GITHUB_ENV + echo "CC=gcc" >> $GITHUB_ENV + echo "CXX=g++" >> $GITHUB_ENV - name: Install apt packages if: startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update sudo apt-get install bison cython3 flex libfl-dev libopenmpi-dev \ - ninja-build openmpi-bin python3-dev python3-numpy python3-pytest \ - python3-pytest-cov + ninja-build openmpi-bin python3-dev + python3 -m pip install --upgrade numpy pytest pytest-cov echo "CC=gcc" >> $GITHUB_ENV echo "CXX=g++" >> $GITHUB_ENV