diff --git a/arbor/fvm_layout.cpp b/arbor/fvm_layout.cpp index 1d5415c7d9297d3c134b3910c63489e90e3b5886..ffc86d5e711885b4f1c3e75245a7594486536627 100644 --- a/arbor/fvm_layout.cpp +++ b/arbor/fvm_layout.cpp @@ -12,6 +12,7 @@ #include <arbor/util/optional.hpp> #include "fvm_layout.hpp" +#include "threading/threading.hpp" #include "util/maputil.hpp" #include "util/meta.hpp" #include "util/partition.hpp" @@ -446,12 +447,16 @@ fvm_cv_discretization fvm_cv_discretize(const cable_cell& cell, const cable_cell } fvm_cv_discretization fvm_cv_discretize(const std::vector<cable_cell>& cells, - const cable_cell_parameter_set& global_defaults) + const cable_cell_parameter_set& global_defaults, + const arb::execution_context& ctx) { - fvm_cv_discretization combined; + std::vector<fvm_cv_discretization> cell_disc(cells.size()); + threading::parallel_for::apply(0, cells.size(), ctx.thread_pool.get(), + [&] (int i) { cell_disc[i]=fvm_cv_discretize(cells[i], global_defaults);}); - for (const auto& c: cells) { - append(combined, fvm_cv_discretize(c, global_defaults)); + fvm_cv_discretization combined; + for (auto cell_idx: count_along(cells)) { + append(combined, cell_disc[cell_idx]); } return combined; } @@ -511,11 +516,15 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties& const cable_cell& cell, const fvm_cv_discretization& D, fvm_size_type cell_idx); fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties& gprop, - const std::vector<cable_cell>& cells, const fvm_cv_discretization& D) + const std::vector<cable_cell>& cells, const fvm_cv_discretization& D, const execution_context& ctx) { + std::vector<fvm_mechanism_data> cell_mech(cells.size()); + threading::parallel_for::apply(0, cells.size(), ctx.thread_pool.get(), + [&] (int i) { cell_mech[i]=fvm_build_mechanism_data(gprop, cells[i], D, i);}); + fvm_mechanism_data combined; for (auto cell_idx: count_along(cells)) { - append(combined, fvm_build_mechanism_data(gprop, cells[cell_idx], D, cell_idx)); + append(combined, cell_mech[cell_idx]); } return combined; } diff --git a/arbor/fvm_layout.hpp b/arbor/fvm_layout.hpp index 3e634cd372f107c76562f79be62ae3b96c3655d9..1c5566f81482c94f8941ed2f5bf49f7d3deaa418 100644 --- a/arbor/fvm_layout.hpp +++ b/arbor/fvm_layout.hpp @@ -11,6 +11,7 @@ #include <arbor/mechcat.hpp> #include <arbor/recipe.hpp> +#include "execution_context.hpp" #include "util/piecewise.hpp" #include "util/rangeutil.hpp" #include "util/span.hpp" @@ -112,7 +113,7 @@ fvm_cv_discretization& append(fvm_cv_discretization&, const fvm_cv_discretizatio // Construct fvm_cv_discretization from one or more cells. fvm_cv_discretization fvm_cv_discretize(const cable_cell& cell, const cable_cell_parameter_set& global_dflt); -fvm_cv_discretization fvm_cv_discretize(const std::vector<cable_cell>& cells, const cable_cell_parameter_set& global_defaults); +fvm_cv_discretization fvm_cv_discretize(const std::vector<cable_cell>& cells, const cable_cell_parameter_set& global_defaults, const arb::execution_context& ctx={}); // Post-discretization data for point and density mechanism instantiation. @@ -172,6 +173,6 @@ struct fvm_mechanism_data { std::size_t n_target = 0; }; -fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties& gprop, const std::vector<cable_cell>& cells, const fvm_cv_discretization& D); +fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties& gprop, const std::vector<cable_cell>& cells, const fvm_cv_discretization& D, const arb::execution_context& ctx={}); } // namespace arb diff --git a/arbor/fvm_lowered_cell_impl.hpp b/arbor/fvm_lowered_cell_impl.hpp index 15580a16633350c052ebb972c411a53b5fb95d8c..23ecd5035d56caeea5f8c8900959f8ef7456047e 100644 --- a/arbor/fvm_lowered_cell_impl.hpp +++ b/arbor/fvm_lowered_cell_impl.hpp @@ -356,15 +356,17 @@ void fvm_lowered_cell_impl<B>::initialize( std::vector<cable_cell> cells; const std::size_t ncell = gids.size(); - cells.reserve(ncell); - for (auto gid: gids) { - try { - cells.push_back(any_cast<cable_cell>(rec.get_cell_description(gid))); - } - catch (util::bad_any_cast&) { - throw bad_cell_description(rec.get_cell_kind(gid), gid); - } - } + cells.resize(ncell); + threading::parallel_for::apply(0, gids.size(), context_.thread_pool.get(), + [&](cell_size_type i) { + auto gid = gids[i]; + try { + cells[i] = any_cast<cable_cell&&>(rec.get_cell_description(gid)); + } + catch (util::bad_any_cast&) { + throw bad_cell_description(rec.get_cell_kind(gid), gid); + } + }); cable_cell_global_properties global_props; try { @@ -397,7 +399,7 @@ void fvm_lowered_cell_impl<B>::initialize( // Discretize cells, build matrix. - fvm_cv_discretization D = fvm_cv_discretize(cells, global_props.default_parameters); + fvm_cv_discretization D = fvm_cv_discretize(cells, global_props.default_parameters, context_); std::vector<index_type> cv_to_intdom(D.size()); std::transform(D.geometry.cv_to_cell.begin(), D.geometry.cv_to_cell.end(), cv_to_intdom.begin(), @@ -410,7 +412,7 @@ void fvm_lowered_cell_impl<B>::initialize( // Discretize mechanism data. - fvm_mechanism_data mech_data = fvm_build_mechanism_data(global_props, cells, D); + fvm_mechanism_data mech_data = fvm_build_mechanism_data(global_props, cells, D, context_); // Discretize and build gap junction info. diff --git a/arbor/include/arbor/cable_cell.hpp b/arbor/include/arbor/cable_cell.hpp index f8b62eb1e545c89222efa2f2ec1f131889588666..fd876e1e2182f406f2057588fda10d6a26677128 100644 --- a/arbor/include/arbor/cable_cell.hpp +++ b/arbor/include/arbor/cable_cell.hpp @@ -99,6 +99,8 @@ public: /// Move constructor cable_cell(cable_cell&& other) = default; + cable_cell& operator=(cable_cell&&) = default; + /// construct from morphology cable_cell(const class morphology& m, const label_dict& dictionary={}); diff --git a/test/unit/test_fvm_lowered.cpp b/test/unit/test_fvm_lowered.cpp index 5f7b116ebe0fa9570832583d0ed7a698e4007778..c6b15e562aac01c5cd41814e902c7471fd46329b 100644 --- a/test/unit/test_fvm_lowered.cpp +++ b/test/unit/test_fvm_lowered.cpp @@ -334,7 +334,7 @@ TEST(fvm_lowered, stimulus) { cable_cell_global_properties gprop; gprop.default_parameters = neuron_parameter_defaults; - fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters); + fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters, context); const auto& A = D.cv_area; std::vector<target_handle> targets; @@ -837,7 +837,7 @@ TEST(fvm_lowered, gj_coords_simple) { cells.push_back(std::move(c)); } - fvm_cv_discretization D = fvm_cv_discretize(cells, neuron_parameter_defaults); + fvm_cv_discretization D = fvm_cv_discretize(cells, neuron_parameter_defaults, context); std::vector<cell_gid_type> gids = {0, 1}; auto GJ = fvcell.fvm_gap_junctions(cells, gids, rec, D); @@ -943,7 +943,7 @@ TEST(fvm_lowered, gj_coords_complex) { gap_recipe rec; fvcell.fvm_intdom(rec, gids, cell_to_intdom); - fvm_cv_discretization D = fvm_cv_discretize(cells, neuron_parameter_defaults); + fvm_cv_discretization D = fvm_cv_discretize(cells, neuron_parameter_defaults, context); int c0_gj_cv[2]; for (int i = 0; i<2; ++i) c0_gj_cv[i] = D.geometry.location_cv(0, c0_gj[i]); @@ -1043,8 +1043,8 @@ TEST(fvm_lowered, cell_group_gj) { auto num_dom0 = fvcell.fvm_intdom(rec, gids_cg0, cell_to_intdom0); auto num_dom1 = fvcell.fvm_intdom(rec, gids_cg1, cell_to_intdom1); - fvm_cv_discretization D0 = fvm_cv_discretize(cell_group0, neuron_parameter_defaults); - fvm_cv_discretization D1 = fvm_cv_discretize(cell_group1, neuron_parameter_defaults); + fvm_cv_discretization D0 = fvm_cv_discretize(cell_group0, neuron_parameter_defaults, context); + fvm_cv_discretization D1 = fvm_cv_discretize(cell_group1, neuron_parameter_defaults, context); auto GJ0 = fvcell.fvm_gap_junctions(cell_group0, gids_cg0, rec, D0); auto GJ1 = fvcell.fvm_gap_junctions(cell_group1, gids_cg1, rec, D1);