Skip to content

Commit 7659031

Browse files
authored
Conditionally post process distances in NN Descent for use with distance epilogue (#1108)
Current implementation of nn descent post processes distances for `L2SqrtExpanded` and `InnerProduct` for efficiency. However, this may cause issues when using a distance epilogue. This PR checks if distances can be postprocessed based on the distance epilogue type, and if not, attempts to compute the full accurate distance instead of postprocessing. Authors: - Jinsol Park (https://github.com/jinsolp) Approvers: - Corey J. Nolet (https://github.com/cjnolet) URL: #1108
1 parent df0fefc commit 7659031

2 files changed

Lines changed: 24 additions & 10 deletions

File tree

cpp/src/neighbors/detail/nn_descent.cuh

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include <optional>
5454
#include <queue>
5555
#include <random>
56+
#include <type_traits>
5657

5758
namespace cuvs::neighbors::nn_descent::detail {
5859

@@ -566,6 +567,10 @@ __launch_bounds__(BLOCK_SIZE)
566567

567568
__syncthreads();
568569

570+
// if we have a distance epilogue, distances need to be fully calculated instead of postprocessing
571+
// them.
572+
bool can_postprocess_dist = std::is_same_v<DistEpilogue_t, raft::identity_op>;
573+
569574
remove_duplicates(new_neighbors,
570575
list_new_size2.x,
571576
new_neighbors + list_new_size2.x,
@@ -638,7 +643,7 @@ __launch_bounds__(BLOCK_SIZE)
638643
int col_id = i / SKEWED_MAX_NUM_BI_SAMPLES;
639644

640645
if (row_id < list_new_size && col_id < list_new_size) {
641-
if (metric == cuvs::distance::DistanceType::InnerProduct) {
646+
if (metric == cuvs::distance::DistanceType::InnerProduct && can_postprocess_dist) {
642647
s_distances[i] = -s_distances[i];
643648
} else if (metric == cuvs::distance::DistanceType::CosineExpanded) {
644649
s_distances[i] = 1.0 - s_distances[i];
@@ -658,6 +663,9 @@ __launch_bounds__(BLOCK_SIZE)
658663
// for fp32 vs fp16 precision differences resulting in negative distances when distance
659664
// should be 0 related issue: https://github.com/rapidsai/cuvs/issues/991
660665
s_distances[i] = s_distances[i] < 0.0f ? 0.0f : s_distances[i];
666+
if (!can_postprocess_dist && metric == cuvs::distance::DistanceType::L2SqrtExpanded) {
667+
s_distances[i] = sqrtf(s_distances[i]);
668+
}
661669
}
662670
s_distances[i] = dist_epilogue(s_distances[i], new_neighbors[row_id], new_neighbors[col_id]);
663671
} else {
@@ -737,7 +745,7 @@ __launch_bounds__(BLOCK_SIZE)
737745
int row_id = i % SKEWED_MAX_NUM_BI_SAMPLES;
738746
int col_id = i / SKEWED_MAX_NUM_BI_SAMPLES;
739747
if (row_id < list_old_size && col_id < list_new_size) {
740-
if (metric == cuvs::distance::DistanceType::InnerProduct) {
748+
if (metric == cuvs::distance::DistanceType::InnerProduct && can_postprocess_dist) {
741749
s_distances[i] = -s_distances[i];
742750
} else if (metric == cuvs::distance::DistanceType::CosineExpanded) {
743751
s_distances[i] = 1.0 - s_distances[i];
@@ -757,6 +765,9 @@ __launch_bounds__(BLOCK_SIZE)
757765
// for fp32 vs fp16 precision differences resulting in negative distances when distance
758766
// should be 0 related issue: https://github.com/rapidsai/cuvs/issues/991
759767
s_distances[i] = s_distances[i] < 0.0f ? 0.0f : s_distances[i];
768+
if (!can_postprocess_dist && metric == cuvs::distance::DistanceType::L2SqrtExpanded) {
769+
s_distances[i] = sqrtf(s_distances[i]);
770+
}
760771
}
761772
s_distances[i] = dist_epilogue(s_distances[i], old_neighbors[row_id], new_neighbors[col_id]);
762773
} else {
@@ -1257,10 +1268,12 @@ void GNND<Data_t, Index_t>::build(Data_t* data,
12571268
auto output_dist_view = raft::make_device_matrix_view<DistData_t, int64_t, raft::row_major>(
12581269
output_distances, nrow_, build_config_.output_graph_degree);
12591270
// distance post-processing
1260-
if (build_config_.metric == cuvs::distance::DistanceType::L2SqrtExpanded) {
1271+
bool can_postprocess_dist = std::is_same_v<DistEpilogue_t, raft::identity_op>;
1272+
if (build_config_.metric == cuvs::distance::DistanceType::L2SqrtExpanded &&
1273+
can_postprocess_dist) {
12611274
raft::linalg::map(
12621275
res, output_dist_view, raft::sqrt_op{}, raft::make_const_mdspan(output_dist_view));
1263-
} else if (!cuvs::distance::is_min_close(build_config_.metric)) {
1276+
} else if (!cuvs::distance::is_min_close(build_config_.metric) && can_postprocess_dist) {
12641277
// revert negated innerproduct
12651278
raft::linalg::map(res,
12661279
output_dist_view,

cpp/tests/neighbors/ann_nn_descent.cuh

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -498,12 +498,13 @@ const std::vector<AnnNNDescentInputs> inputsLargeBatch =
498498
{0.90});
499499

500500
const std::vector<AnnNNDescentInputs> inputsDistEpilogue =
501-
raft::util::itertools::product<AnnNNDescentInputs>({2000, 4000}, // n_rows
502-
{64, 1024}, // dim
503-
{32, 64}, // graph_degree
504-
{cuvs::distance::DistanceType::L2Expanded},
505-
{true}, // data on host
506-
{0.90});
501+
raft::util::itertools::product<AnnNNDescentInputs>(
502+
{2000, 4000}, // n_rows
503+
{64, 1024}, // dim
504+
{32, 64}, // graph_degree
505+
{cuvs::distance::DistanceType::L2Expanded, cuvs::distance::DistanceType::L2SqrtExpanded},
506+
{true}, // data on host
507+
{0.90});
507508

508509
const std::vector<AnnNNDescentBatchInputs> inputsBatch =
509510
raft::util::itertools::product<AnnNNDescentBatchInputs>(

0 commit comments

Comments
 (0)