Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch std::string -> hashes for label resolution. #2215

Merged
merged 13 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions arbor/benchmark_cell_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ benchmark_cell_group::benchmark_cell_group(const std::vector<cell_gid_type>& gid
for (const auto& c: cells_) {
cg_sources.add_cell();
cg_targets.add_cell();
cg_sources.add_label(c.source, {0, 1});
cg_targets.add_label(c.target, {0, 1});
cg_sources.add_label(internal_hash(c.source), {0, 1});
cg_targets.add_label(internal_hash(c.target), {0, 1});
}

benchmark_cell_group::reset();
Expand Down
18 changes: 12 additions & 6 deletions arbor/cable_cell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ struct cable_cell_impl {
decor decorations;

// The placeable label to lid_range map
dynamic_typed_map<constant_type<std::unordered_multimap<cell_tag_type, lid_range>>::type> labeled_lid_ranges;
dynamic_typed_map<constant_type<std::unordered_multimap<hash_type, lid_range>>::type> labeled_lid_ranges;

cable_cell_impl(const arb::morphology& m, const label_dict& labels, const decor& decorations):
provider(m, labels),
Expand Down Expand Up @@ -120,7 +120,7 @@ struct cable_cell_impl {
}

template <typename Item>
void place(const locset& ls, const Item& item, const cell_tag_type& label) {
void place(const locset& ls, const Item& item, const hash_type& label) {
auto& mm = get_location_map(item);
cell_lid_type& lid = placed_count.get<Item>();
cell_lid_type first = lid;
Expand Down Expand Up @@ -226,7 +226,8 @@ void cable_cell_impl::init(const decor& d) {
for (const auto& p: d.placements()) {
auto& where = std::get<0>(p);
auto& label = std::get<2>(p);
std::visit([this, &where, &label] (auto&& what) {return this->place(where, what, label);}, std::get<1>(p));
std::visit([this, &where, &label] (auto&& what) {return this->place(where, what, label); },
std::get<1>(p));
}
}

Expand Down Expand Up @@ -280,16 +281,21 @@ const cable_cell_parameter_set& cable_cell::default_parameters() const {
return impl_->decorations.defaults();
}

const std::unordered_multimap<cell_tag_type, lid_range>& cable_cell::detector_ranges() const {
const cable_cell::lid_range_map& cable_cell::detector_ranges() const {
return impl_->labeled_lid_ranges.get<threshold_detector>();
}

const std::unordered_multimap<cell_tag_type, lid_range>& cable_cell::synapse_ranges() const {
const cable_cell::lid_range_map& cable_cell::synapse_ranges() const {
return impl_->labeled_lid_ranges.get<synapse>();
}

const std::unordered_multimap<cell_tag_type, lid_range>& cable_cell::junction_ranges() const {
const cable_cell::lid_range_map& cable_cell::junction_ranges() const {
return impl_->labeled_lid_ranges.get<junction>();
}

cell_tag_type decor::tag_of(hash_type hash) const {
if (!hashes_.count(hash)) throw arbor_internal_error{util::pprintf("Unknown hash for {}.", std::to_string(hash))};
return hashes_.at(hash);
}

} // namespace arb
9 changes: 8 additions & 1 deletion arbor/cable_cell_param.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
#include <arbor/cable_cell_param.hpp>
#include <arbor/s_expr.hpp>

#include "util/hash.hpp"
#include "util/maputil.hpp"
#include "util/strprintf.hpp"

namespace arb {

Expand Down Expand Up @@ -120,7 +122,12 @@ decor& decor::paint(region where, paintable what) {
}

decor& decor::place(locset where, placeable what, cell_tag_type label) {
placements_.emplace_back(std::move(where), std::move(what), std::move(label));
auto hash = internal_hash(label);
if (hashes_.count(hash) && hashes_.at(hash) != label) {
throw arbor_internal_error{util::strprintf("Hash collision {} ./. {}", label, hashes_.at(hash))};
}
placements_.emplace_back(std::move(where), std::move(what), hash);
hashes_.emplace(hash, label);
return *this;
}

Expand Down
12 changes: 5 additions & 7 deletions arbor/communication/mpi_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,11 @@ struct mpi_context_impl {
}

cell_label_range gather_cell_label_range(const cell_label_range& local_ranges) const {
std::vector<cell_size_type> sizes;
std::vector<cell_tag_type> labels;
std::vector<lid_range> ranges;
sizes = mpi::gather_all(local_ranges.sizes(), comm_);
labels = mpi::gather_all(local_ranges.labels(), comm_);
ranges = mpi::gather_all(local_ranges.ranges(), comm_);
return cell_label_range(sizes, labels, ranges);
cell_label_range res;
res.sizes = mpi::gather_all(local_ranges.sizes, comm_);
res.labels = mpi::gather_all(local_ranges.labels, comm_);
res.ranges = mpi::gather_all(local_ranges.ranges, comm_);
return res;
}

cell_labels_and_gids gather_cell_labels_and_gids(const cell_labels_and_gids& local_labels_and_gids) const {
Expand Down
43 changes: 17 additions & 26 deletions arbor/fvm_lowered_cell_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,21 @@ fvm_detector_info get_detector_info(arb_size_type max,
return { max, std::move(cv), std::move(threshold), ctx };
}

inline cell_size_type
add_labels(cell_label_range& clr, const cable_cell::lid_range_map& ranges) {
clr.add_cell();
cell_size_type count = 0;
std::unordered_map<hash_type, cell_tag_type> hashes;
for (const auto& [label, range]: ranges) {
clr.add_label(label, range);
count += (range.end - range.begin);
}
return count;
}

template <typename Backend>
fvm_initialization_data fvm_lowered_cell_impl<Backend>::initialize(
const std::vector<cell_gid_type>& gids,
const recipe& rec)
{
fvm_initialization_data fvm_lowered_cell_impl<Backend>::initialize(const std::vector<cell_gid_type>& gids,
const recipe& rec) {
using std::any_cast;
using util::count_along;
using util::make_span;
Expand Down Expand Up @@ -346,28 +356,9 @@ fvm_initialization_data fvm_lowered_cell_impl<Backend>::initialize(
for (auto i : util::make_span(ncell)) {
auto gid = gids[i];
const auto& c = cells[i];

fvm_info.source_data.add_cell();
fvm_info.target_data.add_cell();
fvm_info.gap_junction_data.add_cell();

unsigned count = 0;
for (const auto& [label, range]: c.detector_ranges()) {
fvm_info.source_data.add_label(label, range);
count+=(range.end - range.begin);
}
fvm_info.num_sources[gid] = count;

count = 0;
for (const auto& [label, range]: c.synapse_ranges()) {
fvm_info.target_data.add_label(label, range);
count+=(range.end - range.begin);
}
fvm_info.num_targets[gid] = count;

for (const auto& [label, range]: c.junction_ranges()) {
fvm_info.gap_junction_data.add_label(label, range);
}
fvm_info.num_sources[gid] = add_labels(fvm_info.source_data, c.detector_ranges());
fvm_info.num_targets[gid] = add_labels(fvm_info.target_data, c.synapse_ranges());
add_labels(fvm_info.gap_junction_data, c.junction_ranges());
}

cable_cell_global_properties global_props;
Expand Down
10 changes: 5 additions & 5 deletions arbor/include/arbor/cable_cell.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ using cable_cell_location_map = static_typed_map<location_assignment,
synapse, junction, i_clamp, threshold_detector>;

// High-level abstract representation of a cell.
class ARB_SYMBOL_VISIBLE cable_cell {
public:
struct ARB_SYMBOL_VISIBLE cable_cell {
using lid_range_map = std::unordered_multimap<hash_type, lid_range>;
using index_type = cell_lid_type;
using size_type = cell_local_size_type;
using value_type = double;
Expand Down Expand Up @@ -311,9 +311,9 @@ class ARB_SYMBOL_VISIBLE cable_cell {
const cable_cell_parameter_set& default_parameters() const;

// The labeled lid_ranges of sources, targets and gap_junctions on the cell;
const std::unordered_multimap<cell_tag_type, lid_range>& detector_ranges() const;
const std::unordered_multimap<cell_tag_type, lid_range>& synapse_ranges() const;
const std::unordered_multimap<cell_tag_type, lid_range>& junction_ranges() const;
const lid_range_map& detector_ranges() const;
const lid_range_map& synapse_ranges() const;
const lid_range_map& junction_ranges() const;

private:
std::unique_ptr<cable_cell_impl, void (*)(cable_cell_impl*)> impl_;
Expand Down
5 changes: 4 additions & 1 deletion arbor/include/arbor/cable_cell_param.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,9 @@ struct ARB_ARBOR_API cable_cell_parameter_set {
// are to be applied to a morphology in a cable_cell.
class ARB_ARBOR_API decor {
std::vector<std::pair<region, paintable>> paintings_;
std::vector<std::tuple<locset, placeable, cell_tag_type>> placements_;
std::vector<std::tuple<locset, placeable, hash_type>> placements_;
cable_cell_parameter_set defaults_;
std::unordered_map<hash_type, cell_tag_type> hashes_;

public:
const auto& paintings() const {return paintings_; }
Expand All @@ -324,6 +325,8 @@ class ARB_ARBOR_API decor {
decor& paint(region, paintable);
decor& place(locset, placeable, cell_tag_type);
decor& set_default(defaultable);

cell_tag_type tag_of(hash_type) const;
};

ARB_ARBOR_API extern cable_cell_parameter_set neuron_parameter_defaults;
Expand Down
4 changes: 4 additions & 0 deletions arbor/include/arbor/common_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

namespace arb {

// Internal hashes use this 64bit id

using hash_type = std::uint64_t;

// For identifying cells globally.

using cell_gid_type = std::uint32_t;
Expand Down
2 changes: 1 addition & 1 deletion arbor/include/arbor/cv_policy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@

namespace arb {

class cable_cell;
struct cable_cell;

struct cv_policy_base {
virtual locset cv_boundary_points(const cable_cell& cell) const = 0;
Expand Down
62 changes: 38 additions & 24 deletions arbor/label_resolution.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <iterator>
#include <vector>
#include <unordered_set>

#include <arbor/assert.hpp>
#include <arbor/arbexcept.hpp>
Expand All @@ -17,39 +18,49 @@ namespace arb {
cell_label_range::cell_label_range(std::vector<cell_size_type> size_vec,
std::vector<cell_tag_type> label_vec,
std::vector<lid_range> range_vec):
sizes_(std::move(size_vec)), labels_(std::move(label_vec)), ranges_(std::move(range_vec))
sizes(std::move(size_vec)), ranges(std::move(range_vec))
{
std::transform(label_vec.begin(), label_vec.end(),
std::back_inserter(labels),
internal_hash);
arb_assert(check_invariant());
};

cell_label_range::cell_label_range(std::vector<cell_size_type> size_vec,
std::vector<hash_type> label_vec,
std::vector<lid_range> range_vec):
sizes(std::move(size_vec)), labels(std::move(label_vec)), ranges(std::move(range_vec))
{
arb_assert(check_invariant());
};

void cell_label_range::add_cell() {
sizes_.push_back(0);
}

void cell_label_range::add_label(cell_tag_type label, lid_range range) {
if (sizes_.empty()) throw arbor_internal_error("adding label to cell_label_range without cell");
++sizes_.back();
labels_.push_back(std::move(label));
ranges_.push_back(std::move(range));
void cell_label_range::add_cell() { sizes.push_back(0); }

void cell_label_range::add_label(hash_type label, lid_range range) {
if (sizes.empty()) throw arbor_internal_error("adding label to cell_label_range without cell");
++sizes.back();
labels.push_back(label);
ranges.push_back(std::move(range));
}

void cell_label_range::append(cell_label_range other) {
using std::make_move_iterator;
sizes_.insert(sizes_.end(), make_move_iterator(other.sizes_.begin()), make_move_iterator(other.sizes_.end()));
labels_.insert(labels_.end(), make_move_iterator(other.labels_.begin()), make_move_iterator(other.labels_.end()));
ranges_.insert(ranges_.end(), make_move_iterator(other.ranges_.begin()), make_move_iterator(other.ranges_.end()));
sizes.insert(sizes.end(), make_move_iterator(other.sizes.begin()), make_move_iterator(other.sizes.end()));
labels.insert(labels.end(), make_move_iterator(other.labels.begin()), make_move_iterator(other.labels.end()));
ranges.insert(ranges.end(), make_move_iterator(other.ranges.begin()), make_move_iterator(other.ranges.end()));
}

bool cell_label_range::check_invariant() const {
const cell_size_type count = std::accumulate(sizes_.begin(), sizes_.end(), cell_size_type(0));
return count==labels_.size() && count==ranges_.size();
const cell_size_type count = std::accumulate(sizes.begin(), sizes.end(), cell_size_type(0));
return count==labels.size() && count==ranges.size();
}

// cell_labels_and_gids methods
cell_labels_and_gids::cell_labels_and_gids(cell_label_range lr, std::vector<cell_gid_type> gid):
label_range(std::move(lr)), gids(std::move(gid))
{
if (label_range.sizes().size()!=gids.size()) throw arbor_internal_error("cell_label_range and gid count mismatch");
if (label_range.sizes.size()!=gids.size()) throw arbor_internal_error("cell_label_range and gid count mismatch");
}

void cell_labels_and_gids::append(cell_labels_and_gids other) {
Expand All @@ -58,7 +69,7 @@ void cell_labels_and_gids::append(cell_labels_and_gids other) {
}

bool cell_labels_and_gids::check_invariant() const {
return label_range.check_invariant() && label_range.sizes().size()==gids.size();
return label_range.check_invariant() && label_range.sizes.size()==gids.size();
}

// label_resolution_map methods
Expand All @@ -82,34 +93,35 @@ lid_hopefully label_resolution_map::range_set::at(unsigned idx) const {
}

const label_resolution_map::range_set& label_resolution_map::at(cell_gid_type gid, const cell_tag_type& tag) const {
return map.at(gid).at(tag);
return map.at(gid).at(internal_hash(tag));
}

std::size_t label_resolution_map::count(cell_gid_type gid, const cell_tag_type& tag) const {
if (!map.count(gid)) return 0u;
return map.at(gid).count(tag);
return map.at(gid).count(internal_hash(tag));
}

label_resolution_map::label_resolution_map(const cell_labels_and_gids& clg) {
arb_assert(clg.label_range.check_invariant());
const auto& gids = clg.gids;
const auto& labels = clg.label_range.labels();
const auto& ranges = clg.label_range.ranges();
const auto& sizes = clg.label_range.sizes();
const auto& labels = clg.label_range.labels;
const auto& ranges = clg.label_range.ranges;
const auto& sizes = clg.label_range.sizes;

std::vector<cell_size_type> label_divs;
auto partn = util::make_partition(label_divs, sizes);
for (auto i: util::count_along(partn)) {
auto gid = gids[i];

std::unordered_map<cell_tag_type, range_set> m;
std::unordered_map<hash_type, range_set> m;
for (auto label_idx: util::make_span(partn[i])) {
const auto range = ranges[label_idx];
auto size = int(range.end - range.begin);
if (size < 0) {
throw arb::arbor_internal_error("label_resolution_map: invalid lid_range");
}
auto& range_set = m[labels[label_idx]];
auto& label = labels[label_idx];
auto& range_set = m[label];
range_set.ranges.push_back(range);
range_set.ranges_partition.push_back(range_set.ranges_partition.back() + size);
}
Expand Down Expand Up @@ -204,10 +216,12 @@ lid_hopefully update_state(resolver::state_variant& v,
cell_lid_type resolver::resolve(cell_gid_type gid, const cell_local_label_type& label) {
const auto& [tag, pol] = label;

auto hash = internal_hash(tag);

if (!label_map_->count(gid, tag)) throw arb::bad_connection_label(gid, tag, "label does not exist");
const auto& range_set = label_map_->at(gid, tag);

auto& state = state_map_[gid][tag];
auto& state = state_map_[gid][hash];

// Policy round_robin_halt: use previous state of round_robin policy, if existent
if (pol == lid_selection_policy::round_robin_halt
Expand Down
Loading
Loading