Skip to content

Commit

Permalink
Further optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
SiberiaWolfP committed Mar 4, 2024
1 parent ac54a7d commit a3fa824
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 30 deletions.
19 changes: 14 additions & 5 deletions duckpgq/src/duckpgq/functions/scalar/shortest_path_lowerbound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@

namespace duckdb {

static bool IterativeLengthLowerBound(int64_t v_size, int64_t *V, vector<int64_t> &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<int64_t> &E,
int16_t lane_to_num[LANE_LIMIT],
vector<int64_t> &edge_ids,
vector<vector<unordered_map<int64_t, int64_t>>> &paths_v,
vector<vector<unordered_map<int64_t, int64_t>>> &paths_e,
Expand All @@ -22,7 +23,6 @@ static bool IterativeLengthLowerBound(int64_t v_size, int64_t *V, vector<int64_t
bool change = false;
for (auto v = 0; v < v_size; v++) {
next[v] = 0;
seen[v] = 0;
}
//! Keep track of edge id through which the node was reached
for (auto v = 0; v < v_size; v++) {
Expand All @@ -42,7 +42,10 @@ static bool IterativeLengthLowerBound(int64_t v_size, int64_t *V, vector<int64_t
}

for (auto v = 0; v < v_size; v++) {
seen[v] = seen[v] | next[v];
if (seen_check) {
next[v] = next[v] & ~seen[v];
seen[v] = seen[v] | next[v];
}
change |= next[v].any();
}
return change;
Expand Down Expand Up @@ -95,6 +98,8 @@ static void ShortestPathLowerBoundFunction(DataChunk &args,
auto result_data = FlatVector::GetData<list_entry_t>(result);
ValidityMask &result_validity = FlatVector::Validity(result);

bool seen_check = false;

// create temp SIMD arrays
vector<std::bitset<LANE_LIMIT>> seen(v_size);
vector<std::bitset<LANE_LIMIT>> visit1(v_size);
Expand All @@ -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++) {
Expand Down Expand Up @@ -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;
}
Expand Down
57 changes: 38 additions & 19 deletions duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,22 @@ static bool IterativeLengthPhaseTwo(int64_t v_size, int64_t *V, vector<int64_t>
return change;
}

static std::tuple<int64_t, vector<int64_t>> ShortestPathInternal(int64_t lane, int64_t v_size, int64_t destination,
static vector<int64_t> ShortestPathInternal(int64_t lane, int64_t v_size, int64_t destination,
int64_t bound,
int64_t *v, vector<int64_t> &e, vector<int64_t> &edge_ids,
vector<std::bitset<LANE_LIMIT>> &visit) {
vector<std::bitset<LANE_LIMIT>> &visit,
vector<std::bitset<LANE_LIMIT>> &seen,
vector<std::bitset<LANE_LIMIT>> &visit1,
vector<std::bitset<LANE_LIMIT>> &visit2,
vector<std::vector<int64_t>> &parents_v,
vector<std::vector<int64_t>> &parents_e) {
vector<int64_t> src;
vector<int64_t> result;
vector<vector<int64_t>> results;
for (int64_t v = 0; v < v_size; v++) {
if (visit[v][lane]) {
src.push_back(v);
}
}
vector<std::bitset<LANE_LIMIT>> seen(v_size);
vector<std::bitset<LANE_LIMIT>> visit1(v_size);
vector<std::bitset<LANE_LIMIT>> visit2(v_size);

vector<std::vector<int64_t>> parents_v(v_size,
std::vector<int64_t>(LANE_LIMIT, -1));
vector<std::vector<int64_t>> parents_e(v_size,
std::vector<int64_t>(LANE_LIMIT, -1));


// maps lane to search number
int16_t lane_to_num[LANE_LIMIT];
Expand Down Expand Up @@ -139,6 +135,7 @@ static std::tuple<int64_t, vector<int64_t>> 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<int64_t> result;

// found the destination, reconstruct the path
auto parent_vertex = parents_v[destination][lane];
Expand All @@ -155,12 +152,24 @@ static std::tuple<int64_t, vector<int64_t>> 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;

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_eh, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_eh, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_mvp, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_mvp, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_threads, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_threads, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_mvp, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_mvp, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_threads, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_threads, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_eh, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]

Check warning on line 161 in duckpgq/src/duckpgq/functions/scalar/shortest_path_two_phase.cpp

View workflow job for this annotation

GitHub Actions / Build extension binaries / DuckDB-Wasm (wasm_eh, wasm32-emscripten)

implicit conversion from 'long long' to 'size_t' (aka 'unsigned long') changes value from 9223372036854775807 to 4294967295 [-Wconstant-conversion]
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,
Expand Down Expand Up @@ -263,16 +272,26 @@ static void ShortestPathTwoPhaseFunction(DataChunk &args, ExpressionState &state
}
}
if (iter == lower_bound) {
// resource reuse
vector<std::bitset<LANE_LIMIT>> seen_in(v_size);
vector<std::bitset<LANE_LIMIT>> visit1_in(v_size);
vector<std::bitset<LANE_LIMIT>> visit2_in(v_size);

vector<std::vector<int64_t>> parents_v_in(v_size,
std::vector<int64_t>(LANE_LIMIT, -1));
vector<std::vector<int64_t>> parents_e_in(v_size,
std::vector<int64_t>(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<int64_t> 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;
Expand All @@ -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);
}

Expand Down
12 changes: 6 additions & 6 deletions test/sql/path-finding/shortest_path_bound.test
Original file line number Diff line number Diff line change
Expand Up @@ -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]


Expand Down

0 comments on commit a3fa824

Please sign in to comment.