Skip to content

Commit 9d9fe0c

Browse files
author
RomaLzhih
committed
feat(tree): copy input points before all batch operations
1 parent a7bfe80 commit 9d9fe0c

18 files changed

Lines changed: 111 additions & 56 deletions

docs/MANUAL.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,22 +188,19 @@ Then we can use the tree as follows:
188188
- Build the tree:
189189
```c++
190190
Points points;
191-
auto points_copy = points;
192-
tree.Build(points_copy);
191+
tree.Build(points);
193192
```
194193
- Batch Insert:
195194
```c++
196195
Points insert_points;
197-
auto insert_copy = insert_points;
198-
tree.BatchInsert(insert_copy);
196+
tree.BatchInsert(insert_points);
199197
```
200198

201199
- Batch Delete (assumes all points to be deleted are in the tree, use `BatchDiff` if you are not sure):
202200
```c++
203201
Points delete_points;
204-
auto delete_copy = delete_points;
205-
tree.BatchDelete(delete_copy);
206-
// tree.BatchDiff(delete_copy);
202+
tree.BatchDelete(delete_points);
203+
// tree.BatchDiff(delete_points);
207204
```
208205

209206
- KNN query

example/kd_tree.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,7 @@ void run_example() {
150150

151151
// 2. Build the KdTree
152152
Tree tree;
153-
auto points_copy =
154-
points; // WARN: Important! The input array will be changed during build.
155-
tree.Build(parlay::make_slice(points_copy));
153+
tree.Build(parlay::make_slice(points));
156154
std::cout << "Built KdTree with " << n << " points" << std::endl;
157155

158156
// 3. K-Nearest Neighbors query
@@ -203,16 +201,14 @@ void run_example() {
203201
new_points[i].aug.id = n + i;
204202
});
205203

206-
Points insert_copy(new_points); // same as build
207-
tree.BatchInsert(parlay::make_slice(insert_copy));
204+
tree.BatchInsert(parlay::make_slice(new_points));
208205
std::cout << "Inserted " << insert_count << " new points" << std::endl;
209206

210207
// 6. Batch delete some points
211208
size_t delete_count = 50;
212209
Points points_to_delete = points.subseq(0, delete_count);
213210

214-
Points delete_copy(points_to_delete); // same as build
215-
tree.BatchDelete(parlay::make_slice(delete_copy));
211+
tree.BatchDelete(parlay::make_slice(points_to_delete));
216212
std::cout << "Deleted " << delete_count << " points" << std::endl;
217213

218214
// 7. Clean up

example/orth_tree.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,6 @@ void run_example() {
199199
// 2. Build the OrthTree
200200
// OrthTree requires a bounding box to be specified
201201
Tree tree;
202-
auto points_copy =
203-
points; // WARN: Important! The input array will be changed during build.
204202

205203
// Calculate bounding box for the points
206204
// NOTE: This is not necessary, unless you want to specify a certain bounding
@@ -211,7 +209,7 @@ void run_example() {
211209
<< bounding_box.first[1] << "), (" << bounding_box.second[0] << ", "
212210
<< bounding_box.second[1] << ")]" << std::endl;
213211

214-
tree.Build(parlay::make_slice(points_copy), bounding_box);
212+
tree.Build(parlay::make_slice(points), bounding_box);
215213
std::cout << "Built OrthTree (quadtree) with " << n << " points" << std::endl;
216214

217215
// 3. K-Nearest Neighbors query
@@ -262,16 +260,14 @@ void run_example() {
262260
new_points[i].aug.id = n + i;
263261
});
264262

265-
Points insert_copy(new_points); // same as build
266-
tree.BatchInsert(parlay::make_slice(insert_copy));
263+
tree.BatchInsert(parlay::make_slice(new_points));
267264
std::cout << "Inserted " << insert_count << " new points" << std::endl;
268265

269266
// 6. Batch delete some points
270267
size_t delete_count = 50;
271268
Points points_to_delete = points.subseq(0, delete_count);
272269

273-
Points delete_copy(points_to_delete); // same as build
274-
tree.BatchDelete(parlay::make_slice(delete_copy));
270+
tree.BatchDelete(parlay::make_slice(points_to_delete));
275271
std::cout << "Deleted " << delete_count << " points" << std::endl;
276272

277273
// 7. Clean up

example/p_tree.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ void run_example() {
7878

7979
// 2. Build the PTree
8080
Tree tree;
81-
auto points_copy =
82-
points; // WARN: Important! The input array will be changed during build.
83-
tree.Build(parlay::make_slice(points_copy));
81+
tree.Build(parlay::make_slice(points));
8482
std::cout << "Built PTree with " << n << " points using Morton curve"
8583
<< std::endl;
8684

@@ -132,16 +130,14 @@ void run_example() {
132130
new_points[i].aug.id = n + i;
133131
});
134132

135-
Points insert_copy(new_points); // same as build
136-
tree.BatchInsert(parlay::make_slice(insert_copy));
133+
tree.BatchInsert(parlay::make_slice(new_points));
137134
std::cout << "Inserted " << insert_count << " new points" << std::endl;
138135

139136
// 6. Batch delete some points
140137
size_t delete_count = 50;
141138
Points points_to_delete = points.subseq(0, delete_count);
142139

143-
Points delete_copy(points_to_delete); // same as build
144-
tree.BatchDelete(parlay::make_slice(delete_copy));
140+
tree.BatchDelete(parlay::make_slice(points_to_delete));
145141
std::cout << "Deleted " << delete_count << " points" << std::endl;
146142

147143
// 7. Clean up

include/psi/kd_tree.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,10 @@ class KdTree : public BaseTree<Point,
8484

8585
constexpr void DeleteTree() override;
8686

87-
void BatchInsert(Slice In);
87+
template <typename Range>
88+
void BatchInsert(Range&& In);
89+
90+
void BatchInsert_(Slice In);
8891

8992
Node* BatchInsertRecursive(Node* T, Slice In, Slice Out, DimsType d);
9093

include/psi/kd_tree_impl/kd_batch_delete.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight,
1818
static_assert(std::is_constructible_v<parlay::range_value_type_t<Range>,
1919
parlay::range_reference_type_t<Range>>);
2020

21-
Slice A = parlay::make_slice(In);
21+
auto aux = Points::uninitialized(parlay::size(In));
22+
parlay::copy(In, parlay::make_slice(aux));
23+
Slice A = parlay::make_slice(aux);
2224
BatchDelete_(A);
2325
return;
2426
}

include/psi/kd_tree_impl/kd_batch_diff.hpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,31 @@
44
#include "../kd_tree.h"
55

66
namespace psi {
7-
template <typename Point, typename SplitRule, typename LeafAugType, typename InteriorAugType, uint_fast8_t kSkHeight,
7+
template <typename Point, typename SplitRule, typename LeafAugType,
8+
typename InteriorAugType, uint_fast8_t kSkHeight,
89
uint_fast8_t kImbaRatio>
910
template <typename Range>
10-
void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight , kImbaRatio>::BatchDiff(Range&& In) {
11+
void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight,
12+
kImbaRatio>::BatchDiff(Range&& In) {
1113
static_assert(parlay::is_random_access_range_v<Range>);
1214
static_assert(
1315
parlay::is_less_than_comparable_v<parlay::range_reference_type_t<Range>>);
1416
static_assert(std::is_constructible_v<parlay::range_value_type_t<Range>,
1517
parlay::range_reference_type_t<Range>>);
1618

17-
Slice A = parlay::make_slice(In);
19+
auto aux = Points::uninitialized(parlay::size(In));
20+
parlay::copy(In, parlay::make_slice(aux));
21+
Slice A = parlay::make_slice(aux);
1822
BatchDiff_(A);
1923
return;
2024
}
2125

2226
// NOTE: batch delete suitable for Points that are pratially covered in the tree
23-
template <typename Point, typename SplitRule, typename LeafAugType, typename InteriorAugType, uint_fast8_t kSkHeight,
27+
template <typename Point, typename SplitRule, typename LeafAugType,
28+
typename InteriorAugType, uint_fast8_t kSkHeight,
2429
uint_fast8_t kImbaRatio>
25-
void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight , kImbaRatio>::BatchDiff_(Slice A) {
30+
void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight,
31+
kImbaRatio>::BatchDiff_(Slice A) {
2632
Points B = Points::uninitialized(A.size());
2733
Node* T = this->root_;
2834
Box box = this->tree_box_;
@@ -55,13 +61,17 @@ void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight , kImbaRat
5561

5662
// NOTE: only sieve the Points, without rebuilding the tree
5763
// NOTE: the kdtree needs box since the box will be changed in batch diff
58-
template <typename Point, typename SplitRule, typename LeafAugType, typename InteriorAugType, uint_fast8_t kSkHeight,
64+
template <typename Point, typename SplitRule, typename LeafAugType,
65+
typename InteriorAugType, uint_fast8_t kSkHeight,
5966
uint_fast8_t kImbaRatio>
60-
typename KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight , kImbaRatio>::NodeBox
61-
KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight , kImbaRatio>::BatchDiffRecursive(
62-
Node* T,
63-
typename KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight , kImbaRatio>::Box const& box,
64-
Slice In, Slice Out, DimsType d) {
67+
typename KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight,
68+
kImbaRatio>::NodeBox
69+
KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight, kImbaRatio>::
70+
BatchDiffRecursive(
71+
Node* T,
72+
typename KdTree<Point, SplitRule, LeafAugType, InteriorAugType,
73+
kSkHeight, kImbaRatio>::Box const& box,
74+
Slice In, Slice Out, DimsType d) {
6575
size_t n = In.size();
6676

6777
if (n == 0) return NodeBox(T, box);

include/psi/kd_tree_impl/kd_batch_insert.hpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,29 @@
55
#include "parlay/slice.h"
66

77
namespace psi {
8-
template <typename Point, typename SplitRule, typename LeafAugType, typename InteriorAugType, uint_fast8_t kSkHeight,
8+
template <typename Point, typename SplitRule, typename LeafAugType,
9+
typename InteriorAugType, uint_fast8_t kSkHeight,
910
uint_fast8_t kImbaRatio>
10-
void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight , kImbaRatio>::BatchInsert(Slice A) {
11+
template <typename Range>
12+
void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight,
13+
kImbaRatio>::BatchInsert(Range&& In) {
14+
static_assert(parlay::is_random_access_range_v<Range>);
15+
static_assert(
16+
parlay::is_less_than_comparable_v<parlay::range_reference_type_t<Range>>);
17+
static_assert(std::is_constructible_v<parlay::range_value_type_t<Range>,
18+
parlay::range_reference_type_t<Range>>);
19+
20+
auto aux = Points::uninitialized(parlay::size(In));
21+
parlay::copy(In, parlay::make_slice(aux));
22+
Slice A = parlay::make_slice(aux);
23+
BatchInsert_(A);
24+
}
25+
26+
template <typename Point, typename SplitRule, typename LeafAugType,
27+
typename InteriorAugType, uint_fast8_t kSkHeight,
28+
uint_fast8_t kImbaRatio>
29+
void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight,
30+
kImbaRatio>::BatchInsert_(Slice A) {
1131
if (this->root_ == nullptr) { // TODO: may check using explicity tag
1232
return Build_(A);
1333
}
@@ -26,10 +46,12 @@ void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight , kImbaRat
2646
}
2747

2848
// NOTE: return the updated Node
29-
template <typename Point, typename SplitRule, typename LeafAugType, typename InteriorAugType, uint_fast8_t kSkHeight,
49+
template <typename Point, typename SplitRule, typename LeafAugType,
50+
typename InteriorAugType, uint_fast8_t kSkHeight,
3051
uint_fast8_t kImbaRatio>
31-
Node* KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight , kImbaRatio>::BatchInsertRecursive(
32-
Node* T, Slice In, Slice Out, DimsType d) {
52+
Node* KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight,
53+
kImbaRatio>::BatchInsertRecursive(Node* T, Slice In, Slice Out,
54+
DimsType d) {
3355
size_t n = In.size();
3456

3557
if (n == 0) return T;

include/psi/kd_tree_impl/kd_build_tree.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ void KdTree<Point, SplitRule, LeafAugType, InteriorAugType, kSkHeight,
2121
static_assert(std::is_constructible_v<parlay::range_value_type_t<Range>,
2222
parlay::range_reference_type_t<Range>>);
2323

24-
Slice A = parlay::make_slice(In);
24+
auto aux = Points::uninitialized(parlay::size(In));
25+
parlay::copy(In, parlay::make_slice(aux));
26+
Slice A = parlay::make_slice(aux);
2527
Build_(A);
2628
}
2729

include/psi/orth_tree_impl/orth_batch_delete.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ void OrthTree<Point, SplitRule, LeafAugType, InteriorAugType, kMD, kSkHeight,
1818
static_assert(std::is_constructible_v<parlay::range_value_type_t<Range>,
1919
parlay::range_reference_type_t<Range>>);
2020

21-
Slice A = parlay::make_slice(In);
21+
auto aux = Points::uninitialized(parlay::size(In));
22+
parlay::copy(In, parlay::make_slice(aux));
23+
Slice A = parlay::make_slice(aux);
2224
BatchDelete_(A);
2325
return;
2426
}

0 commit comments

Comments
 (0)