Merge pull request #6306 from GilesBathgate/Hash_map-performance_chained_map_reserve-GilesBathgate

Reserve method for Chained Map / Unique Hash Map
This commit is contained in:
Sébastien Loriot 2022-03-29 17:45:37 +02:00
commit b34bc3f8f7
14 changed files with 104 additions and 63 deletions

View File

@ -59,7 +59,7 @@ class chained_map
typedef typename Allocator_traits::template rebind_alloc<chained_map_elem<T> > allocator_type;
allocator_type alloc;
std::size_t reserved_size;
public:
T& xdef() { return STOP.i; }
const T& cxdef() const { return STOP.i; }
@ -70,7 +70,7 @@ private:
chained_map_elem<T>* HASH(std::size_t x) const
{ return table + (x & table_size_1); }
void init_table(std::size_t t);
void init_table(std::size_t n);
void rehash();
void del_old_table();
@ -83,17 +83,19 @@ private:
}
public:
static constexpr std::size_t min_size = 32;
static constexpr std::size_t default_size = 512;
typedef chained_map_elem<T>* chained_map_item;
typedef chained_map_item item;
std::size_t index(chained_map_item it) const { return it->k; }
T& inf(chained_map_item it) const { return it->i; }
chained_map(std::size_t n = 1);
chained_map(std::size_t n = default_size);
chained_map(const chained_map<T, Allocator>& D);
chained_map& operator=(const chained_map<T, Allocator>& D);
void reserve(std::size_t n);
void clear_entries();
void clear();
~chained_map()
@ -104,6 +106,8 @@ public:
destroy(item);
alloc.deallocate(old_table, old_table_end - old_table);
}
if(!table)
return;
for (chained_map_item item = table ; item != table_end ; ++item)
destroy(item);
alloc.deallocate(table, table_end - table);
@ -119,7 +123,11 @@ public:
template <typename T, typename Allocator>
inline T& chained_map<T, Allocator>::access(std::size_t x)
{ chained_map_item p = HASH(x);
{
if(!table)
init_table(reserved_size);
chained_map_item p = HASH(x);
if (old_table) del_old_table();
if ( p->k == x ) {
@ -138,8 +146,11 @@ inline T& chained_map<T, Allocator>::access(std::size_t x)
}
template <typename T, typename Allocator>
void chained_map<T, Allocator>::init_table(std::size_t t)
void chained_map<T, Allocator>::init_table(std::size_t n)
{
std::size_t t = min_size;
while (t < n) t <<= 1;
table_size = t;
table_size_1 = t-1;
table = alloc.allocate(t + t/2);
@ -270,16 +281,9 @@ T& chained_map<T, Allocator>::access(chained_map_item p, std::size_t x)
template <typename T, typename Allocator>
chained_map<T, Allocator>::chained_map(std::size_t n) :
nullptrKEY(0), NONnullptrKEY(1), old_table(0)
chained_map<T, Allocator>::chained_map(std::size_t n)
: nullptrKEY(0), NONnullptrKEY(1), table(nullptr), old_table(0), reserved_size(n)
{
if (n < 512)
init_table(512);
else {
std::size_t ts = 1;
while (ts < n) ts <<= 1;
init_table(ts);
}
}
@ -320,9 +324,20 @@ chained_map<T, Allocator>& chained_map<T, Allocator>::operator=(const chained_ma
return *this;
}
template <typename T, typename Allocator>
void chained_map<T, Allocator>::reserve(std::size_t n)
{
CGAL_assertion(!table);
reserved_size = n;
}
template <typename T, typename Allocator>
void chained_map<T, Allocator>::clear_entries()
{ for(chained_map_item p = table + 1; p < free; p++)
{
if(!table)
return;
for(chained_map_item p = table + 1; p < free; p++)
if (p->k != nullptrKEY || p >= table + table_size)
p->i = T();
}
@ -330,23 +345,30 @@ void chained_map<T, Allocator>::clear_entries()
template <typename T, typename Allocator>
void chained_map<T, Allocator>::clear()
{
if(!table)
return;
clear_entries();
for (chained_map_item item = table ; item != table_end ; ++item)
destroy(item);
alloc.deallocate(table, table_end - table);
init_table(512);
table = nullptr;
}
template <typename T, typename Allocator>
typename chained_map<T, Allocator>::chained_map_item
chained_map<T, Allocator>::lookup(std::size_t x) const
{ chained_map_item p = HASH(x);
{
if(!table)
return nullptr;
chained_map_item p = HASH(x);
((std::size_t &)STOP.k) = x; // cast away const
while (p->k != x)
{ p = p->succ; }
return (p == &STOP) ? 0 : p;
return (p == &STOP) ? nullptr : p;
}

View File

@ -57,7 +57,7 @@ public:
Unique_hash_map() { m_map.xdef() = Data(); }
Unique_hash_map( const Data& deflt, std::size_t table_size = 1)
Unique_hash_map( const Data& deflt, std::size_t table_size = Map::default_size)
: m_map( table_size) { m_map.xdef() = deflt; }
Unique_hash_map( const Data& deflt,
@ -78,6 +78,9 @@ public:
insert( first1, beyond1, first2);
}
void reserve(std::size_t n)
{ m_map.reserve(n); }
Data default_value() const { return m_map.cxdef(); }
Hash_function hash_function() const { return m_hash_function; }

View File

@ -120,6 +120,12 @@ been inserted explicitly. Their variables are initialized to
*/
bool is_defined( const Key& key) const;
/*!
sets the table size.
*/
void reserve(std::size_t table_size);
/*!
resets `*this` to the injective function from `Key` to the

View File

@ -306,7 +306,7 @@ class Binary_operation : public CGAL::SNC_decorator<Map> {
number_of_intersection_candidates=0;
#endif
Unique_hash_map<Vertex_const_handle, bool> ignore(false);
Unique_hash_map<Vertex_const_handle, bool> ignore(false, snc1.number_of_vertices());
Vertex_const_iterator v0;
// CGAL_NEF_SETDTHREAD(19*43*131);

View File

@ -606,6 +606,7 @@ Node_handle build_kdtree(Vertex_list& V, Halfedge_list& E, Halffacet_list& F,
#else
Side_of_plane sop(point_on_plane, coord);
#endif
sop.reserve(V.size());
Vertex_list V1,V2;
classify_objects(V, sop, V1, V2);

View File

@ -110,14 +110,14 @@ struct Sort_sedges2 {
template <typename P, typename V, typename E, typename I>
struct Halffacet_output {
Halffacet_output(CGAL::Unique_hash_map<I,E>& F, std::vector<E>& S)
Halffacet_output(const CGAL::Unique_hash_map<I,E>& F, std::vector<E>& S)
: From(F), Support(S) { edge_number=0; Support[0]=E(); }
typedef P Point;
typedef V Vertex_handle;
typedef unsigned Halfedge_handle;
CGAL::Unique_hash_map<I,E>& From;
const CGAL::Unique_hash_map<I,E>& From;
std::vector<E>& Support;
unsigned edge_number;
@ -467,12 +467,11 @@ create_facet_objects(const Plane_3& plane_supporting_facet,
Object_list_iterator start, Object_list_iterator end) const
{ CGAL_NEF_TRACEN(">>>>>create_facet_objects "
<< normalized(plane_supporting_facet));
CGAL::Unique_hash_map<SHalfedge_handle,int> FacetCycle(-1);
std::vector<SHalfedge_handle> MinimalEdge;
std::list<SHalfedge_handle> SHalfedges;
std::list<SHalfloop_handle> SHalfloops;
CGAL::Unique_hash_map<Segment_iterator,SHalfedge_handle> From;
Segment_list Segments;
SHalfedge_handle e; SHalfloop_handle l;
@ -503,6 +502,7 @@ create_facet_objects(const Plane_3& plane_supporting_facet,
CGAL_error_msg("Damn wrong handle.");
}
CGAL::Unique_hash_map<SHalfedge_handle,int> FacetCycle(-1, SHalfedges.size());
/* We iterate all shalfedges and assign a number for each facet
cycle. After that iteration for an edge |e| the number of its
facet cycle is |FacetCycle[e]| and for a facet cycle |c| we know
@ -606,6 +606,7 @@ create_facet_objects(const Plane_3& plane_supporting_facet,
// Insertion of SHalfedges into Segments is shifted below in order
// to guarantee that there are no gaps in the overlay.
CGAL::Unique_hash_map<Segment_iterator,SHalfedge_handle> From(SHalfedge_handle(), SHalfedges.size());
// SHalfedges.sort(Sort_sedges2<Point_3,SHalfedge_handle>());
SHalfedges.sort(Sort_sedges<Vertex_handle,SHalfedge_handle>());

View File

@ -280,6 +280,7 @@ class SNC_decorator : public SNC_const_decorator<Map> {
SFace_map linked;
Shell_volume_setter(const SNCD_& Di)
: D(Di), linked(false) {}
void reserve(Size_type n) { linked.reserve(n); }
void visit(SFace_handle h) {
CGAL_NEF_TRACEN(h->center_vertex()->point());
D.set_volume(h, c);

View File

@ -796,9 +796,11 @@ public:
// CGAL_NEF_SETDTHREAD(37*43*503*509);
CGAL_NEF_TRACEN(">>>>>create_volumes");
Sface_shell_hash ShellSf(0);
Face_shell_hash ShellF(0);
SFace_visited_hash Done(false);
auto face_count = this->sncp()->number_of_halffacets();
auto sface_count = this->sncp()->number_of_sfaces();
Sface_shell_hash ShellSf(0, sface_count);
Face_shell_hash ShellF(0, face_count);
SFace_visited_hash Done(false, sface_count);
Shell_explorer V(*this,ShellSf,ShellF,Done);
std::vector<SFace_handle> MinimalSFace;
std::vector<SFace_handle> EntrySFace;
@ -828,10 +830,13 @@ public:
Closed.push_back(false);
Halffacet_iterator hf;
CGAL_forall_facets(hf,*this)
if(ShellF[hf] != ShellF[hf->twin()]) {
Closed[ShellF[hf]] = true;
Closed[ShellF[hf->twin()]] = true;
CGAL_forall_facets(hf,*this) {
unsigned int shf = ShellF[hf];
unsigned int shf_twin = ShellF[hf->twin()];
if(shf != shf_twin) {
Closed[shf] = true;
Closed[shf_twin] = true;
}
}
CGAL_assertion( pl != nullptr);
@ -1304,7 +1309,7 @@ public:
link_shalfedges_to_facet_cycles();
std::map<int, int> hash;
CGAL::Unique_hash_map<SHalfedge_handle, bool> done(false);
CGAL::Unique_hash_map<SHalfedge_handle, bool> done(false, this->sncp()->number_of_shalfedges());
SHalfedge_iterator sei;
CGAL_forall_shalfedges(sei, *this->sncp()) {
@ -1381,17 +1386,7 @@ public:
SNC_simplify simp(*this->sncp());
simp.vertex_simplificationI();
// std::map<int, int> hash;
CGAL::Unique_hash_map<SHalfedge_handle, bool>
done(false);
/*
SHalfedge_iterator sei;
CGAL_forall_shalfedges(sei, *this->sncp()) {
hash[sei->get_forward_index()] = sei->get_forward_index();
hash[sei->get_backward_index()] = sei->get_backward_index();
}
*/
categorize_facet_cycles_and_create_facets();
create_volumes();

View File

@ -85,7 +85,7 @@ public:
#else
Side_of_plane(const Point_3& p, int c) : OnSideMap(unknown_side), coord(c), pop(p) {}
#endif
void reserve(std::size_t n) { OnSideMap.reserve(n); }
Oriented_side operator()(Vertex_handle v);
Oriented_side operator()(Halfedge_handle e);
Oriented_side operator()(Halffacet_handle f);

View File

@ -316,9 +316,9 @@ class SNC_simplify_base : public SNC_decorator<SNC_structure> {
CGAL_NEF_TRACEN(">>> simplifying");
SNC_decorator D(*this->sncp());
Unique_hash_map< Volume_handle, UFH_volume> hash_volume;
Unique_hash_map< Halffacet_handle, UFH_facet> hash_facet;
Unique_hash_map< SFace_handle, UFH_sface> hash_sface;
Unique_hash_map< Volume_handle, UFH_volume> hash_volume(UFH_volume(), this->sncp()->number_of_volumes());
Unique_hash_map< Halffacet_handle, UFH_facet> hash_facet(UFH_facet(), this->sncp()->number_of_halffacets());
Unique_hash_map< SFace_handle, UFH_sface> hash_sface(UFH_sface(), this->sncp()->number_of_sfaces());
Union_find< Volume_handle> uf_volume;
Union_find< Halffacet_handle> uf_facet;
Union_find< SFace_handle> uf_sface;
@ -544,7 +544,8 @@ class SNC_simplify_base : public SNC_decorator<SNC_structure> {
void create_boundary_links_forall_sfaces(
Unique_hash_map< SFace_handle, UFH_sface>& hash,
Union_find< SFace_handle>& uf ) {
Unique_hash_map< SHalfedge_handle, bool> linked(false);
Unique_hash_map< SHalfedge_handle, bool> linked(false, this->sncp()->number_of_shalfedges());
SNC_decorator D(*this->sncp());
SHalfedge_iterator e;
CGAL_forall_shalfedges(e, *this->sncp()) {
@ -597,7 +598,7 @@ class SNC_simplify_base : public SNC_decorator<SNC_structure> {
void create_boundary_links_forall_facets(
Unique_hash_map< Halffacet_handle, UFH_facet>& hash,
Union_find< Halffacet_handle>& uf) {
Unique_hash_map< SHalfedge_handle, bool> linked(false);
Unique_hash_map< SHalfedge_handle, bool> linked(false, this->sncp()->number_of_shalfedges());
SNC_decorator D(*this->sncp());
SHalfedge_iterator u;
CGAL_forall_shalfedges(u, *this->sncp()) {
@ -651,6 +652,7 @@ class SNC_simplify_base : public SNC_decorator<SNC_structure> {
SNC_decorator D(*this->sncp());
Volume_setter setter(D);
setter.reserve(this->sncp()->number_of_sfaces());
SFace_iterator sf;
Volume_handle c;

View File

@ -462,6 +462,10 @@ public:
return *this;
}
void reserve_sm_boundary_items(Size_type n) {
sm_boundary_item_.reserve(n);
}
void clear_boundary() {
boundary_item_.clear(boost::none);
sm_boundary_item_.clear(boost::none);
@ -484,10 +488,10 @@ public:
}
template <typename H>
bool is_boundary_object(H h)
bool is_boundary_object(H h) const
{ return boundary_item_[h]!=boost::none; }
template <typename H>
bool is_sm_boundary_object(H h)
bool is_sm_boundary_object(H h) const
{ return sm_boundary_item_[h]!=boost::none; }
template <typename H>
@ -1099,13 +1103,13 @@ template <typename Kernel, typename Items, typename Mark>
void SNC_structure<Kernel,Items,Mark>::
pointer_update(const SNC_structure<Kernel,Items,Mark>& D)
{
CGAL::Unique_hash_map<Vertex_const_handle,Vertex_handle> VM;
CGAL::Unique_hash_map<Halfedge_const_handle,Halfedge_handle> EM;
CGAL::Unique_hash_map<Halffacet_const_handle,Halffacet_handle> FM;
CGAL::Unique_hash_map<Volume_const_handle,Volume_handle> CM;
CGAL::Unique_hash_map<SHalfedge_const_handle,SHalfedge_handle> SEM;
CGAL::Unique_hash_map<SHalfloop_const_handle,SHalfloop_handle> SLM;
CGAL::Unique_hash_map<SFace_const_handle,SFace_handle> SFM;
CGAL::Unique_hash_map<Vertex_const_handle,Vertex_handle> VM(Vertex_handle(), D.number_of_vertices());
CGAL::Unique_hash_map<Halfedge_const_handle,Halfedge_handle> EM(Halfedge_handle(), D.number_of_halfedges());
CGAL::Unique_hash_map<Halffacet_const_handle,Halffacet_handle> FM(Halffacet_handle(), D.number_of_halffacets());
CGAL::Unique_hash_map<Volume_const_handle,Volume_handle> CM(Volume_handle(), D.number_of_volumes());
CGAL::Unique_hash_map<SHalfedge_const_handle,SHalfedge_handle> SEM(SHalfedge_handle(), D.number_of_shalfedges());
CGAL::Unique_hash_map<SHalfloop_const_handle,SHalfloop_handle> SLM(SHalfloop_handle(), D.number_of_shalfloops());
CGAL::Unique_hash_map<SFace_const_handle,SFace_handle> SFM(SFace_handle(), D.number_of_sfaces());
Vertex_const_iterator vc = D.vertices_begin();
Vertex_iterator v = vertices_begin();
for ( ; vc != D.vertices_end(); ++vc,++v) VM[vc] = v;

View File

@ -205,7 +205,6 @@ void polygon_mesh_to_nef_3(PolygonMesh& P, SNC_structure& S, FaceIndexMap fimap,
Face_graph_index_adder<typename SNC_structure::Items,
PolygonMesh, SNC_structure,HalfedgeIndexMap> index_adder(P,himap);
for(vertex_descriptor pv : vertices(P) ) {
typename boost::property_traits<PMap>::reference npv = get(pmap,pv);

View File

@ -355,6 +355,10 @@ protected:
delegate(mbv, /*compute_external*/ false, /*simplify*/ false);
}
void reserve_for_vertices(Size_type n) {
snc().reserve_sm_boundary_items(n);
}
struct Private_tag {};
Nef_polyhedron_3(Private_tag) {
pl() = new SNC_point_locator_default;
@ -615,6 +619,7 @@ protected:
: Nef_polyhedron_3(Private_tag{})
{
CGAL_NEF_TRACEN("construction from Polyhedron_3");
reserve_for_vertices(P.size_of_vertices());
initialize_infibox_vertices(EMPTY);
polyhedron_3_to_nef_3
<CGAL::Polyhedron_3<T1,T2,T3,T4>, SNC_structure>( P, snc());
@ -628,6 +633,7 @@ protected:
: Nef_polyhedron_3(Private_tag{})
{
CGAL_NEF_TRACEN("construction from PolygonMesh with internal index maps");
reserve_for_vertices(num_vertices(pm));
initialize_infibox_vertices(EMPTY);
polygon_mesh_to_nef_3<PolygonMesh, SNC_structure>(const_cast<PolygonMesh&>(pm), snc());
build_external_structure();
@ -645,6 +651,7 @@ protected:
) : Nef_polyhedron_3(Private_tag{})
{
CGAL_NEF_TRACEN("construction from PolygonMesh");
reserve_for_vertices(num_vertices(pm));
initialize_infibox_vertices(EMPTY);
polygon_mesh_to_nef_3<PolygonMesh, SNC_structure>(const_cast<PolygonMesh&>(pm), snc(), fim, him);
build_external_structure();

View File

@ -495,10 +495,10 @@ template <typename K, typename I, typename M>
void Sphere_map<K, I, M>::
pointer_update(const Sphere_map<K, I, M>& D)
{
CGAL::Unique_hash_map<SVertex_const_handle,SVertex_handle> VM;
CGAL::Unique_hash_map<SHalfedge_const_handle,SHalfedge_handle> EM;
CGAL::Unique_hash_map<SHalfloop_const_handle,SHalfloop_handle> LM;
CGAL::Unique_hash_map<SFace_const_handle,SFace_handle> FM;
CGAL::Unique_hash_map<SVertex_const_handle,SVertex_handle> VM(SVertex_handle(), D.number_of_svertices());
CGAL::Unique_hash_map<SHalfedge_const_handle,SHalfedge_handle> EM(SHalfedge_handle(), D.number_of_shalfedges());
CGAL::Unique_hash_map<SHalfloop_const_handle,SHalfloop_handle> LM(SHalfloop_handle(), D.number_of_shalfloops());
CGAL::Unique_hash_map<SFace_const_handle,SFace_handle> FM(SFace_handle(), D.number_of_sfaces());
SVertex_const_iterator vc = D.svertices_begin();
SVertex_iterator v = svertices_begin();