From a3fa824603faf3b61ead7388202ceaefd1c3ef55 Mon Sep 17 00:00:00 2001 From: Pingan Ren Date: Mon, 4 Mar 2024 15:59:52 +0100 Subject: [PATCH] Further optimization --- .../scalar/shortest_path_lowerbound.cpp | 19 +++++-- .../scalar/shortest_path_two_phase.cpp | 57 ++++++++++++------- .../sql/path-finding/shortest_path_bound.test | 12 ++-- 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/duckpgq/src/duckpgq/functions/scalar/shortest_path_lowerbound.cpp b/duckpgq/src/duckpgq/functions/scalar/shortest_path_lowerbound.cpp index e9fa7bff..91f852ea 100644 --- a/duckpgq/src/duckpgq/functions/scalar/shortest_path_lowerbound.cpp +++ b/duckpgq/src/duckpgq/functions/scalar/shortest_path_lowerbound.cpp @@ -11,8 +11,9 @@ namespace duckdb { -static bool IterativeLengthLowerBound(int64_t v_size, int64_t *V, vector &E, - int64_t iter, int16_t lane_to_num[LANE_LIMIT], +static bool IterativeLengthLowerBound(int64_t v_size, int64_t iter, bool seen_check, + int64_t *V, vector &E, + int16_t lane_to_num[LANE_LIMIT], vector &edge_ids, vector>> &paths_v, vector>> &paths_e, @@ -22,7 +23,6 @@ static bool IterativeLengthLowerBound(int64_t v_size, int64_t *V, vector(result); ValidityMask &result_validity = FlatVector::Validity(result); + bool seen_check = false; + // create temp SIMD arrays vector> seen(v_size); vector> visit1(v_size); @@ -114,6 +119,7 @@ static void ShortestPathLowerBoundFunction(DataChunk &args, idx_t started_searches = 0; while (started_searches < args.size()) { + seen_check = false; // empty visit vectors for (auto i = 0; i < v_size; i++) { @@ -145,9 +151,12 @@ static void ShortestPathLowerBoundFunction(DataChunk &args, //! make passes while a lane is still active for (int64_t iter = 1; active && iter <= upper_bound; iter++) { + if (iter >= lower_bound) { + seen_check = true; + } //! Perform one step of bfs exploration if (!IterativeLengthLowerBound( - v_size, v, e, iter, lane_to_num, edge_ids, paths_v, paths_e, seen, + v_size, iter, seen_check, v, e, lane_to_num, edge_ids, paths_v, paths_e, seen, (iter & 1) ? visit1 : visit2, (iter & 1) ? visit2 : visit1)) { break; } diff --git a/duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp b/duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp index 25be0a84..d49709f5 100644 --- a/duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp +++ b/duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp @@ -81,26 +81,22 @@ static bool IterativeLengthPhaseTwo(int64_t v_size, int64_t *V, vector return change; } -static std::tuple> ShortestPathInternal(int64_t lane, int64_t v_size, int64_t destination, +static vector ShortestPathInternal(int64_t lane, int64_t v_size, int64_t destination, int64_t bound, int64_t *v, vector &e, vector &edge_ids, - vector> &visit) { + vector> &visit, + vector> &seen, + vector> &visit1, + vector> &visit2, + vector> &parents_v, + vector> &parents_e) { vector src; - vector result; + vector> results; for (int64_t v = 0; v < v_size; v++) { if (visit[v][lane]) { src.push_back(v); } } - vector> seen(v_size); - vector> visit1(v_size); - vector> visit2(v_size); - - vector> parents_v(v_size, - std::vector(LANE_LIMIT, -1)); - vector> parents_e(v_size, - std::vector(LANE_LIMIT, -1)); - // maps lane to search number int16_t lane_to_num[LANE_LIMIT]; @@ -139,6 +135,7 @@ static std::tuple> ShortestPathInternal(int64_t lane, i for (int64_t lane = 0; lane < LANE_LIMIT; lane++) { if (seen[destination][lane]) { auto search_num = lane_to_num[lane]; + vector result; // found the destination, reconstruct the path auto parent_vertex = parents_v[destination][lane]; @@ -155,12 +152,24 @@ static std::tuple> ShortestPathInternal(int64_t lane, i } result.push_back(src[search_num]); std::reverse(result.begin(), result.end()); - return std::make_tuple(src[search_num], result); + results.push_back(result); + break; } } } } - return std::make_tuple(-1, result); + size_t min_size = INT64_MAX; + size_t min_index = -1; + for (size_t i = 0; i < results.size(); i++) { + if (results[i].size() < min_size) { + min_size = results[i].size(); + min_index = i; + } + } + if (min_index >= 0) { + return results[min_index]; + } + return {}; } static void ShortestPathTwoPhaseFunction(DataChunk &args, ExpressionState &state, @@ -263,16 +272,26 @@ static void ShortestPathTwoPhaseFunction(DataChunk &args, ExpressionState &state } } if (iter == lower_bound) { + // resource reuse + vector> seen_in(v_size); + vector> visit1_in(v_size); + vector> visit2_in(v_size); + + vector> parents_v_in(v_size, + std::vector(LANE_LIMIT, -1)); + vector> parents_e_in(v_size, + std::vector(LANE_LIMIT, -1)); + for (int64_t lane = 0; lane < LANE_LIMIT; lane++) { auto search_num = lane_to_num[lane]; if (search_num >= 0) { int64_t dst_pos = vdata_dst.sel->get_index(search_num); auto phase_two_result = ShortestPathInternal(lane, v_size, dst_data[dst_pos], - upper_bound - lower_bound + 1, v, e, edge_ids, (iter & 1) ? visit1 : visit2); - auto phase_two_src = std::get<0>(phase_two_result); - auto phase_two_path = std::get<1>(phase_two_result); - if (phase_two_src >= 0) { + upper_bound - lower_bound + 1, v, e, edge_ids, (iter & 1) ? visit1 : visit2, + seen_in, visit1_in, visit2_in, parents_v_in, parents_e_in); + if (phase_two_result.size() > 0) { vector output_vector; + auto phase_two_src = phase_two_result[0]; // construct the path of phase one if (paths_v[phase_two_src][lane].size() > 0) { auto iterations = lower_bound - 1; @@ -290,7 +309,7 @@ static void ShortestPathTwoPhaseFunction(DataChunk &args, ExpressionState &state } // construct the path of phase two - for (auto val : phase_two_path) { + for (auto val : phase_two_result) { output_vector.push_back(val); } diff --git a/test/sql/path-finding/shortest_path_bound.test b/test/sql/path-finding/shortest_path_bound.test index da12c592..ca139ae9 100644 --- a/test/sql/path-finding/shortest_path_bound.test +++ b/test/sql/path-finding/shortest_path_bound.test @@ -333,19 +333,19 @@ query III ---- 0 0 [0, 0, 2, 1, 0] 0 1 [0, 0, 2, 2, 3, 4, 1] -0 2 [0, 0, 2, 1, 0, 0, 2] +0 2 [0, 0, 2, 2, 3, 3, 2] 0 3 [0, 0, 2, 2, 3] 1 0 [1, 6, 1, 5, 0] 1 1 [1, 6, 1, 6, 1] 1 2 [1, 5, 0, 0, 2] 1 3 [1, 5, 0, 0, 2, 2, 3] -2 0 [2, 1, 0, 0, 2, 1, 0] +2 0 [2, 2, 3, 3, 2, 1, 0] 2 1 [2, 2, 3, 4, 1] -2 2 [2, 1, 0, 0, 2] -2 3 [2, 1, 0, 0, 2, 2, 3] -3 0 [3, 4, 1, 5, 0] +2 2 [2, 2, 3, 3, 2] +2 3 [2, 2, 3, 3, 2, 2, 3] +3 0 [3, 3, 2, 1, 0] 3 1 [3, 4, 1, 6, 1] -3 2 [3, 4, 1, 5, 0, 0, 2] +3 2 [3, 3, 2, 2, 3, 3, 2] 3 3 [3, 3, 2, 2, 3]