From b25ec434a4453971577b316af6bf8e66fd6526ba Mon Sep 17 00:00:00 2001 From: eric bryant Date: Mon, 30 Dec 2019 19:09:21 -0500 Subject: [PATCH 1/4] faster unique location detection for quadtree insert --- .../cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp | 5 +++-- siteupdate/python-teresco/siteupdate.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp index c02f731f..1f7b10e0 100644 --- a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp +++ b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp @@ -35,14 +35,15 @@ void WaypointQuadtree::insert(Waypoint *w) { // insert Waypoint *w into this quadtree node //std::cout << "QTDEBUG: " << str() << " insert " << w->str() << std::endl; if (!refined()) - { if (!waypoint_at_same_point(w)) + { + if (!w->colocated || w == w->colocated->back()) { //std::cout << "QTDEBUG: " << str() << " at " << unique_locations << " unique locations" << std::endl; unique_locations++; } points.push_front(w); if (unique_locations > 50) // 50 unique points max per quadtree node refine(); - } + } else if (w->lat < mid_lat) if (w->lng < mid_lng) sw_child->insert(w); diff --git a/siteupdate/python-teresco/siteupdate.py b/siteupdate/python-teresco/siteupdate.py index 7ca2aa37..8bb7bcde 100755 --- a/siteupdate/python-teresco/siteupdate.py +++ b/siteupdate/python-teresco/siteupdate.py @@ -77,7 +77,7 @@ def insert(self,w): """insert Waypoint w into this quadtree node""" #print("QTDEBUG: " + str(self) + " insert " + str(w)) if self.points is not None: - if self.waypoint_at_same_point(w) is None: + if w.colocated is None or w == w.colocated[0]: #print("QTDEBUG: " + str(self) + " at " + str(self.unique_locations) + " unique locations") self.unique_locations += 1 self.points.append(w) From d247442592e72ed4219a2d22251a2eda43870dd1 Mon Sep 17 00:00:00 2001 From: eric bryant Date: Mon, 30 Dec 2019 19:54:04 -0500 Subject: [PATCH 2/4] colocation detection during quadtree insertion ...rather than before --- .../cplusplus/classes/Route/read_wpt.cpp | 14 +------ .../WaypointQuadtree/WaypointQuadtree.cpp | 32 ++++++++++++---- .../WaypointQuadtree/WaypointQuadtree.h | 2 +- siteupdate/python-teresco/siteupdate.py | 37 +++++++++++-------- 4 files changed, 48 insertions(+), 37 deletions(-) diff --git a/siteupdate/cplusplus/classes/Route/read_wpt.cpp b/siteupdate/cplusplus/classes/Route/read_wpt.cpp index 3c330b31..a910c9c9 100644 --- a/siteupdate/cplusplus/classes/Route/read_wpt.cpp +++ b/siteupdate/cplusplus/classes/Route/read_wpt.cpp @@ -63,20 +63,8 @@ void Route::read_wpt if (al[c] >= 'a' && al[c] <= 'z') al[c] -= 32; unused_alt_labels.insert(al); } - // look for colocated points all_waypoints->mtx.lock(); - Waypoint *other_w = all_waypoints->waypoint_at_same_point(w); - if (other_w) - { // see if this is the first point colocated with other_w - if (!other_w->colocated) - { other_w->colocated = new std::list; - // deleted on termination of program - other_w->colocated->push_front(other_w); - } - other_w->colocated->push_front(w); - w->colocated = other_w->colocated; - } - all_waypoints->insert(w); + all_waypoints->insert(w, 1); all_waypoints->mtx.unlock(); // single-point Datachecks, and HighwaySegment diff --git a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp index 1f7b10e0..79f80786 100644 --- a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp +++ b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp @@ -27,15 +27,33 @@ void WaypointQuadtree::refine() sw_child = new WaypointQuadtree(min_lat, min_lng, mid_lat, mid_lng); se_child = new WaypointQuadtree(min_lat, mid_lng, mid_lat, max_lng); // deleted on termination of program - for (Waypoint *p : points) insert(p); + for (Waypoint *p : points) insert(p, 0); points.clear(); } -void WaypointQuadtree::insert(Waypoint *w) +void WaypointQuadtree::insert(Waypoint *w, bool init) { // insert Waypoint *w into this quadtree node //std::cout << "QTDEBUG: " << str() << " insert " << w->str() << std::endl; if (!refined()) - { + { // look for colocated points during initial insertion + if (init) + { Waypoint *other_w = 0; + for (Waypoint *p : points) + if (p->same_coords(w)) + { other_w = p; + break; + } + if (other_w) + { // see if this is the first point colocated with other_w + if (!other_w->colocated) + { other_w->colocated = new std::list; + // deleted on termination of program + other_w->colocated->push_front(other_w); + } + other_w->colocated->push_front(w); + w->colocated = other_w->colocated; + } + } if (!w->colocated || w == w->colocated->back()) { //std::cout << "QTDEBUG: " << str() << " at " << unique_locations << " unique locations" << std::endl; unique_locations++; @@ -46,11 +64,11 @@ void WaypointQuadtree::insert(Waypoint *w) } else if (w->lat < mid_lat) if (w->lng < mid_lng) - sw_child->insert(w); - else se_child->insert(w); + sw_child->insert(w, init); + else se_child->insert(w, init); else if (w->lng < mid_lng) - nw_child->insert(w); - else ne_child->insert(w); + nw_child->insert(w, init); + else ne_child->insert(w, init); } Waypoint *WaypointQuadtree::waypoint_at_same_point(Waypoint *w) diff --git a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h index 1d24001c..ca6dff1a 100644 --- a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h +++ b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h @@ -12,7 +12,7 @@ class WaypointQuadtree bool refined(); WaypointQuadtree(double, double, double, double); void refine(); - void insert(Waypoint*); + void insert(Waypoint*, bool); Waypoint *waypoint_at_same_point(Waypoint*); std::forward_list near_miss_waypoints(Waypoint*, double); std::string str(); diff --git a/siteupdate/python-teresco/siteupdate.py b/siteupdate/python-teresco/siteupdate.py index 8bb7bcde..ec399b3d 100755 --- a/siteupdate/python-teresco/siteupdate.py +++ b/siteupdate/python-teresco/siteupdate.py @@ -71,12 +71,25 @@ def refine(self): points = self.points self.points = None for p in points: - self.insert(p) + self.insert(p, False) - def insert(self,w): + def insert(self,w,init): """insert Waypoint w into this quadtree node""" #print("QTDEBUG: " + str(self) + " insert " + str(w)) if self.points is not None: + # look for colocated points during initial insertion + if init: + other_w = None + for p in self.points: + if p.same_coords(w): + other_w = p + break + if other_w is not None: + # see if this is the first point colocated with other_w + if other_w.colocated is None: + other_w.colocated = [ other_w ] + other_w.colocated.append(w) + w.colocated = other_w.colocated if w.colocated is None or w == w.colocated[0]: #print("QTDEBUG: " + str(self) + " at " + str(self.unique_locations) + " unique locations") self.unique_locations += 1 @@ -86,14 +99,14 @@ def insert(self,w): else: if w.lat < self.mid_lat: if w.lng < self.mid_lng: - self.sw_child.insert(w) + self.sw_child.insert(w, init) else: - self.se_child.insert(w) + self.se_child.insert(w, init) else: if w.lng < self.mid_lng: - self.nw_child.insert(w) + self.nw_child.insert(w, init) else: - self.ne_child.insert(w) + self.ne_child.insert(w, init) def waypoint_at_same_point(self,w): """find an existing waypoint at the same coordinates as w""" @@ -928,16 +941,8 @@ def read_wpt(self,all_waypoints,all_waypoints_lock,datacheckerrors,el,path="../. # populate unused alt labels for label in w.alt_labels: self.unused_alt_labels.add(label.upper().strip("+")) - # look for colocated points - all_waypoints_lock.acquire() - other_w = all_waypoints.waypoint_at_same_point(w) - if other_w is not None: - # see if this is the first point colocated with other_w - if other_w.colocated is None: - other_w.colocated = [ other_w ] - other_w.colocated.append(w) - w.colocated = other_w.colocated + all_waypoints_lock.acquire() # look for near-miss points (before we add this one in) #print("DEBUG: START search for nmps for waypoint " + str(w) + " in quadtree of size " + str(all_waypoints.size())) #if not all_waypoints.is_valid(): @@ -959,7 +964,7 @@ def read_wpt(self,all_waypoints,all_waypoints_lock,datacheckerrors,el,path="../. else: other_w.near_miss_points.append(w) - all_waypoints.insert(w) + all_waypoints.insert(w, True) all_waypoints_lock.release() # add HighwaySegment, if not first point if previous_point is not None: From ef1894f3f57c251089781862db7bd358aa1418dd Mon Sep 17 00:00:00 2001 From: eric bryant Date: Mon, 30 Dec 2019 23:02:42 -0500 Subject: [PATCH 3/4] recursive_mutex for every quadtree node --- siteupdate/cplusplus/classes/Route/read_wpt.cpp | 2 -- .../classes/WaypointQuadtree/WaypointQuadtree.cpp | 8 +++++--- .../cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/siteupdate/cplusplus/classes/Route/read_wpt.cpp b/siteupdate/cplusplus/classes/Route/read_wpt.cpp index a910c9c9..f130c9ba 100644 --- a/siteupdate/cplusplus/classes/Route/read_wpt.cpp +++ b/siteupdate/cplusplus/classes/Route/read_wpt.cpp @@ -63,9 +63,7 @@ void Route::read_wpt if (al[c] >= 'a' && al[c] <= 'z') al[c] -= 32; unused_alt_labels.insert(al); } - all_waypoints->mtx.lock(); all_waypoints->insert(w, 1); - all_waypoints->mtx.unlock(); // single-point Datachecks, and HighwaySegment w->out_of_bounds(datacheckerrors, fstr); diff --git a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp index 79f80786..b6285089 100644 --- a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp +++ b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.cpp @@ -1,5 +1,3 @@ -std::mutex WaypointQuadtree::mtx; - bool WaypointQuadtree::WaypointQuadtree::refined() { return nw_child; } @@ -34,6 +32,7 @@ void WaypointQuadtree::refine() void WaypointQuadtree::insert(Waypoint *w, bool init) { // insert Waypoint *w into this quadtree node //std::cout << "QTDEBUG: " << str() << " insert " << w->str() << std::endl; + mtx.lock(); if (!refined()) { // look for colocated points during initial insertion if (init) @@ -61,14 +60,17 @@ void WaypointQuadtree::insert(Waypoint *w, bool init) points.push_front(w); if (unique_locations > 50) // 50 unique points max per quadtree node refine(); + mtx.unlock(); } - else if (w->lat < mid_lat) + else { mtx.unlock(); + if (w->lat < mid_lat) if (w->lng < mid_lng) sw_child->insert(w, init); else se_child->insert(w, init); else if (w->lng < mid_lng) nw_child->insert(w, init); else ne_child->insert(w, init); + } } Waypoint *WaypointQuadtree::waypoint_at_same_point(Waypoint *w) diff --git a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h index ca6dff1a..87da2852 100644 --- a/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h +++ b/siteupdate/cplusplus/classes/WaypointQuadtree/WaypointQuadtree.h @@ -7,7 +7,7 @@ class WaypointQuadtree WaypointQuadtree *nw_child, *ne_child, *sw_child, *se_child; std::forward_list points; unsigned int unique_locations; - static std::mutex mtx; + std::recursive_mutex mtx; bool refined(); WaypointQuadtree(double, double, double, double); From 68315717a3802d7ab37a4c86496eae89826f042e Mon Sep 17 00:00:00 2001 From: eric bryant Date: Wed, 18 Mar 2020 23:20:53 -0400 Subject: [PATCH 4/4] fix NmpSearchThread comment --- siteupdate/cplusplus/siteupdate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siteupdate/cplusplus/siteupdate.cpp b/siteupdate/cplusplus/siteupdate.cpp index ffc5ffd8..7eb80d9e 100644 --- a/siteupdate/cplusplus/siteupdate.cpp +++ b/siteupdate/cplusplus/siteupdate.cpp @@ -337,7 +337,7 @@ int main(int argc, char *argv[]) // create NMP lists cout << et.et() << "Searching for near-miss points." << endl; #ifdef threading_enabled - // set up for threaded processing of highway systems + // set up for threaded NMP search hs_it = highway_systems.begin(); for (unsigned int t = 0; t < args.numthreads; t++)