Skip to content

Commit 1ed4678

Browse files
authored
Replace asserts with exceptions in C++ code (#410)
1 parent c93ef9b commit 1ed4678

File tree

13 files changed

+233
-63
lines changed

13 files changed

+233
-63
lines changed

src/include/api/feature_vector_array.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,11 @@ const FeatureVectorArray::tdb_col_major_matrix_with_ids_table_type FeatureVector
361361
using QueryVectorArray = FeatureVectorArray;
362362

363363
bool validate_top_k(const FeatureVectorArray& a, const FeatureVectorArray& b) {
364-
// assert(a.datatype() == b.datatype());
364+
if (a.feature_type() != b.feature_type()) {
365+
throw std::runtime_error(
366+
"[feature_vector_array@validate_top_k] Feature types do not match: " +
367+
a.feature_type_string() + " vs " + b.feature_type_string());
368+
}
365369

366370
auto proc_b = [&b](auto& aview) {
367371
switch (b.feature_type()) {

src/include/detail/graph/best_first.h

Lines changed: 97 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ auto best_first_O1(
121121
auto&& [_, p_star] = frontier.back();
122122
frontier.pop_back();
123123

124-
assert(!(visited.count(p_star) > 0));
124+
if (visited.count(p_star) > 0) {
125+
throw std::runtime_error("[best_first@best_first_O1] Vertex was visited");
126+
}
125127
visited.insert(p_star);
126128

127129
for (auto&& [_, neighbor_id] : graph[p_star]) {
@@ -176,10 +178,13 @@ auto best_first_O2(
176178
enfrontiered.insert(source);
177179

178180
while (!frontier.empty()) {
179-
assert(is_minmax_heap(
180-
frontier.begin(), frontier.end(), [](auto&& a, auto&& b) {
181-
return std::get<0>(a) < std::get<0>(b);
182-
}));
181+
if (!is_minmax_heap(
182+
frontier.begin(), frontier.end(), [](auto&& a, auto&& b) {
183+
return std::get<0>(a) < std::get<0>(b);
184+
})) {
185+
throw std::runtime_error(
186+
"[best_first@best_first_O2] Frontier is not a min-max heap");
187+
}
183188

184189
#if 0
185190
std::cout << "\n\n{\n";
@@ -211,7 +216,9 @@ auto best_first_O2(
211216
frontier.pop_back();
212217
enfrontiered.erase(p_star);
213218

214-
assert(p_star == q_star);
219+
if (p_star != q_star) {
220+
throw std::runtime_error("[best_first@best_first_O2] p_star != q_star");
221+
}
215222

216223
visited.insert(p_star);
217224

@@ -384,7 +391,11 @@ auto best_first_O3(
384391
pq.insert(heuristic, source);
385392
auto&& [source_iter, success] =
386393
vertex_state_map.emplace(std::make_pair(source, 0));
387-
assert(success);
394+
if (!success) {
395+
throw std::runtime_error(
396+
"[best_first@best_first_O3] Could not insert source into "
397+
"vertex_state_map");
398+
}
388399

389400
set_enpqd(source_iter->second);
390401

@@ -396,10 +407,13 @@ auto best_first_O3(
396407
set_enpqd(source_iter->second);
397408

398409
while (!frontier.empty()) {
399-
assert(is_minmax_heap(
400-
frontier.begin(), frontier.end(), [](auto&& a, auto&& b) {
401-
return std::get<0>(a) < std::get<0>(b);
402-
}));
410+
if (!is_minmax_heap(
411+
frontier.begin(), frontier.end(), [](auto&& a, auto&& b) {
412+
return std::get<0>(a) < std::get<0>(b);
413+
})) {
414+
throw std::runtime_error(
415+
"[best_first@best_first_O3] Frontier is not a min-max heap");
416+
}
403417

404418
#if 0
405419
std::cout << "\n\n{\n";
@@ -414,9 +428,11 @@ auto best_first_O3(
414428

415429
auto debug_p_star = p_star;
416430

417-
// assert(vertex_state_map.find(p_star) == vertex_state_map.end());
418431
auto p_star_iter = vertex_state_map.find(p_star);
419-
assert(p_star_iter != vertex_state_map.end());
432+
if (p_star_iter == vertex_state_map.end()) {
433+
throw std::runtime_error(
434+
"[best_first@best_first_O3] p_star_iter == vertex_state_map.end()");
435+
}
420436

421437
pop_minmax_heap_min(
422438
frontier.begin(), frontier.end(), [](auto&& a, auto&& b) {
@@ -443,7 +459,9 @@ auto best_first_O3(
443459
clear_enfrontiered(p_star_iter->second);
444460
set_visited(p_star_iter->second);
445461

446-
assert(p_star == q_star);
462+
if (p_star != q_star) {
463+
throw std::runtime_error("[best_first@best_first_O3] p_star != q_star");
464+
}
447465

448466
score_type min_evicted_score = std::numeric_limits<score_type>::max();
449467
auto evicted_pq = std::vector<node_type>{};
@@ -454,7 +472,11 @@ auto best_first_O3(
454472
if (neighbor_state_iter == vertex_state_map.end()) {
455473
auto [local_neighbor_state_iter, success] =
456474
vertex_state_map.emplace(neighbor_id, 0);
457-
assert(success);
475+
if (!success) {
476+
throw std::runtime_error(
477+
"[best_first@best_first_O3] Could not insert neighbor_id into "
478+
"vertex_state_map");
479+
}
458480
neighbor_state_iter = local_neighbor_state_iter;
459481
} else {
460482
if (!is_unvisited(neighbor_state_iter->second)) {
@@ -472,7 +494,11 @@ auto best_first_O3(
472494
set_enpqd(neighbor_state_iter->second);
473495
if (evicted) {
474496
auto evicted_state_iter = vertex_state_map.find(evicted_id);
475-
assert(evicted_state_iter != vertex_state_map.end());
497+
if (evicted_state_iter == vertex_state_map.end()) {
498+
throw std::runtime_error(
499+
"[best_first@best_first_O3] evicted_state_iter == "
500+
"vertex_state_map.end()");
501+
}
476502

477503
if (is_visited(evicted_state_iter->second)) {
478504
// Only mark as evicted if not visited
@@ -498,7 +524,12 @@ auto best_first_O3(
498524
return std::get<0>(a) < std::get<0>(b);
499525
});
500526

501-
assert(size(frontier) <= size(pq));
527+
if (size(frontier) > size(pq)) {
528+
throw std::runtime_error(
529+
"[best_first@best_first_O3] size(frontier) (" +
530+
std::to_string(size(frontier)) + ") > size(pq) (" +
531+
std::to_string(size(pq)) + ")");
532+
}
502533
// vertex_state_map.erase(p_star);
503534
}
504535
auto top_k = std::vector<id_type>(k_nn);
@@ -585,18 +616,33 @@ auto best_first_O4(
585616
}
586617
clear_enfrontiered(vertex_state_property_map[p_star]);
587618
// std::cout << "p_star " << p_star << std::endl;
588-
assert(is_visited(vertex_state_property_map[p_star]));
589-
assert(!is_evicted(vertex_state_property_map[p_star]));
590-
assert(!is_enfrontiered(vertex_state_property_map[p_star]));
619+
if (!is_visited(vertex_state_property_map[p_star])) {
620+
throw std::runtime_error(
621+
"[best_first@best_first_O4] p_star is not visited");
622+
}
623+
if (is_evicted(vertex_state_property_map[p_star])) {
624+
throw std::runtime_error("[best_first@best_first_O4] p_star is evicted");
625+
}
626+
if (is_enfrontiered(vertex_state_property_map[p_star])) {
627+
throw std::runtime_error(
628+
"[best_first@best_first_O4] p_star is enfrontiered");
629+
}
591630

592631
p_star = std::numeric_limits<id_type>::max();
593632
auto p_min_score = std::numeric_limits<score_type>::max();
594633

595634
for (auto&& [pq_score, pq_id] : pq) {
596635
if (pq_score < p_min_score) {
597636
auto pq_state = vertex_state_property_map[pq_id];
598-
assert(!is_evicted(pq_state));
599-
assert(is_enpqd(pq_state));
637+
638+
if (is_evicted(pq_state)) {
639+
throw std::runtime_error(
640+
"[best_first@best_first_O4] pq_state is evicted");
641+
}
642+
if (!is_enpqd(pq_state)) {
643+
throw std::runtime_error(
644+
"[best_first@best_first_O4] pq_state is not enpqd");
645+
}
600646
if (!is_visited(pq_state)) {
601647
p_star = pq_id;
602648
p_min_score = pq_score;
@@ -646,7 +692,11 @@ auto best_first_O5(
646692
pq.insert(heuristic, source);
647693
auto&& [source_iter, success] =
648694
vertex_state_map.emplace(std::make_pair(source, 0));
649-
assert(success);
695+
if (!success) {
696+
throw std::runtime_error(
697+
"[best_first@best_first_O3] Could not insert source into "
698+
"vertex_state_map");
699+
}
650700

651701
set_enpqd(source_iter->second);
652702

@@ -656,7 +706,10 @@ auto best_first_O5(
656706
visited.insert(p_star);
657707

658708
auto p_star_iter = vertex_state_map.find(p_star);
659-
assert(p_star_iter != vertex_state_map.end());
709+
if (p_star_iter == vertex_state_map.end()) {
710+
throw std::runtime_error(
711+
"[best_first@best_first_O3] p_star_iter == vertex_state_map.end()");
712+
}
660713
clear_enfrontiered(p_star_iter->second);
661714
set_visited(p_star_iter->second);
662715

@@ -666,7 +719,11 @@ auto best_first_O5(
666719
if (neighbor_state_iter == vertex_state_map.end()) {
667720
auto [local_neighbor_state_iter, success] =
668721
vertex_state_map.emplace(neighbor_id, 0);
669-
assert(success);
722+
if (!success) {
723+
throw std::runtime_error(
724+
"[best_first@best_first_O3] Could not insert neighbor_id into "
725+
"vertex_state_map");
726+
}
670727
neighbor_state_iter = local_neighbor_state_iter;
671728
} else {
672729
if (!is_unvisited(neighbor_state_iter->second)) {
@@ -684,7 +741,11 @@ auto best_first_O5(
684741
set_enpqd(neighbor_state_iter->second);
685742
if (evicted) {
686743
auto evicted_state_iter = vertex_state_map.find(evicted_id);
687-
assert(evicted_state_iter != vertex_state_map.end());
744+
if (evicted_state_iter == vertex_state_map.end()) {
745+
throw std::runtime_error(
746+
"[best_first@best_first_O3] evicted_state_iter == "
747+
"vertex_state_map.end()");
748+
}
688749
set_evicted(evicted_state_iter->second);
689750
}
690751
} else {
@@ -697,8 +758,16 @@ auto best_first_O5(
697758

698759
for (auto&& [pq_score, pq_id] : pq) {
699760
auto pq_state_iter = vertex_state_map.find(pq_id);
700-
assert(!is_evicted(pq_state_iter->second));
701-
assert(is_enpqd(pq_state_iter->second));
761+
762+
if (is_evicted(pq_state_iter->second)) {
763+
throw std::runtime_error(
764+
"[best_first@best_first_O3] pq_state_iter is evicted");
765+
}
766+
if (!is_enpqd(pq_state_iter->second)) {
767+
throw std::runtime_error(
768+
"[best_first@best_first_O3] pq_state_iter is not enpqd");
769+
}
770+
702771
if (!is_visited(pq_state_iter->second)) {
703772
if (pq_score < p_min_score) {
704773
p_star = pq_id;

src/include/detail/graph/diskann.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,19 @@ auto read_diskann_mem_index_with_scores(
152152
for (size_t i = 0; i < num_neighbors; ++i) {
153153
uint32_t id;
154154
binary_file.read((char*)&id, 4);
155-
assert(id < num_nodes);
155+
if (id >= num_nodes) {
156+
throw std::runtime_error(
157+
"[read_diskann_mem_index_with_scores] id >= num_nodes");
158+
}
156159
g.add_edge(node, id, l2_distance(x[node], x[id]));
157160
}
158161
++node;
159162
}
160163
binary_file.close();
161-
assert(node == num_nodes);
164+
if (node != num_nodes) {
165+
throw std::runtime_error(
166+
"[read_diskann_mem_index_with_scores] node != num_nodes");
167+
}
162168

163169
return g;
164170
}

src/include/detail/graph/greedy_search.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,11 @@ auto greedy_search_O1(
299299

300300
static_assert(std::integral<id_type>);
301301

302-
assert(L >= k_nn);
302+
if (L < k_nn) {
303+
throw std::runtime_error(
304+
"[greedy_search_O1] L (" + std::to_string(L) + ") < k_nn (" +
305+
std::to_string(k_nn) + ")");
306+
}
303307

304308
std::unordered_set<id_type> visited_vertices;
305309
auto visited = [&visited_vertices](auto&& v) {
@@ -550,7 +554,10 @@ auto robust_prune(
550554
return std::get<0>(a) < std::get<0>(b);
551555
}));
552556

553-
assert(p_star != p);
557+
if (p_star == p) {
558+
throw std::runtime_error("[robust_prune] p_star == p");
559+
}
560+
554561
if (noisy_robust_prune) {
555562
std::cout << "::::" << p_star << std::endl;
556563
debug_min_heap(V, "V: ", 1);

src/include/detail/ivf/dist_qv.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@ auto dist_qv_finite_ram_part(
123123
num_queries,
124124
fixed_min_pair_heap<score_type, shuffled_ids_type>(k_nn));
125125

126-
assert(::num_partitions(partitioned_vectors) == size(dist_active_partitions));
126+
if (::num_partitions(partitioned_vectors) != size(dist_active_partitions)) {
127+
throw std::runtime_error(
128+
"[dist_qv_finite_ram_part] num_partitions(partitioned_vectors) != "
129+
"size(dist_active_partitions)");
130+
}
127131

128132
auto current_part_size = ::num_partitions(partitioned_vectors);
129133
size_t parts_per_thread = (current_part_size + nthreads - 1) / nthreads;
@@ -267,7 +271,12 @@ auto dist_qv_finite_ram(
267271
scoped_timer _{tdb_func__ + " " + part_uri};
268272

269273
// Check that the size of the indices vector is correct
270-
assert(size(indices) == centroids.num_cols() + 1);
274+
if (size(indices) != centroids.num_cols() + 1) {
275+
throw std::runtime_error(
276+
"[dist_qv_finite_ram] size(indices) (" + std::to_string(size(indices)) +
277+
") != centroids.num_cols() + 1 (" +
278+
std::to_string(centroids.num_cols() + 1) + ")");
279+
}
271280

272281
using score_type = float;
273282
using indices_type =

src/include/detail/ivf/index.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,10 @@ int ivf_index(
155155

156156
shuffled_ids[ibin] = external_ids[i];
157157

158-
assert(ibin < shuffled_db.num_cols());
158+
if (ibin >= shuffled_db.num_cols()) {
159+
throw std::runtime_error(
160+
"[ivf_index] ibin >= shuffled_db.num_cols()");
161+
}
159162
for (size_t j = 0; j < db.num_rows(); ++j) {
160163
shuffled_db(j, ibin) = db(j, i);
161164
}
@@ -170,7 +173,10 @@ int ivf_index(
170173

171174
shuffled_ids[ibin] = external_ids[i];
172175

173-
assert(ibin < shuffled_db.num_cols());
176+
if (ibin >= shuffled_db.num_cols()) {
177+
throw std::runtime_error(
178+
"[ivf_index] ibin >= shuffled_db.num_cols()");
179+
}
174180
for (size_t j = 0; j < db.num_rows(); ++j) {
175181
shuffled_db(j, ibin) = db(j, i);
176182
}

src/include/detail/ivf/qv.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,11 @@ auto qv_query_heap_infinite_ram(
132132
[&, nprobe](auto&& q_vec, auto&& n = 0, auto&& j = 0) {
133133
for (size_t p = 0; p < nprobe; ++p) {
134134
auto aa = top_centroids(p, j);
135-
assert(top_centroids(p, j) < size(indices) - 1);
135+
if (top_centroids(p, j) >= size(indices) - 1) {
136+
throw std::runtime_error(
137+
"[qv_query_heap_infinite_ram] top_centroids(p, j) >= "
138+
"size(indices) - 1");
139+
}
136140

137141
size_t start = indices[top_centroids(p, j)];
138142
size_t stop = indices[top_centroids(p, j) + 1];
@@ -648,7 +652,11 @@ auto nuv_query_heap_finite_ram_reg_blocked(
648652
p +
649653
part_offset; // resident_part_offset(partitioned_vectors);
650654

651-
assert(p + 1 < size(indices));
655+
if (p + 1 >= size(indices)) {
656+
throw std::runtime_error(
657+
"[nuv_query_heap_finite_ram_reg_blocked] p + 1 >= "
658+
"size(indices)");
659+
}
652660

653661
auto start = indices[p];
654662
auto stop = indices[p + 1];

0 commit comments

Comments
 (0)