Skip to content

[FEA] Binary IVF Flat Index - #1099

Open
tarang-jain wants to merge 163 commits into
NVIDIA:mainfrom
tarang-jain:binary-kmeans
Open

tarang-jain wants to merge 163 commits into
NVIDIA:mainfrom
tarang-jain:binary-kmeans

Conversation

@tarang-jain

@tarang-jain tarang-jain commented Jul 9, 2025 •

Copy link
Copy Markdown
Contributor

Depends on NVIDIA/raft#2770

Implementation of binary ivf flat index (bitwise hamming metric for the IVF Flat index)

Key Features

1. Binary Index Structure

  • Added binary_centers_ field to store cluster centers as packed uint8_t arrays for binary data
  • Index automatically detects BitwiseHamming metric and configures itself for binary operation
  • Only support uint8_t inputs with BitwiseHamming and add only single instantiations of newly added kernels

2. K-means Clustering for Binary Data

The clustering approach for binary data required special handling:

  • Expanded Space Clustering: Binary data (uint8_t) is expanded to signed representation (int8_t) where each bit becomes ±1

    • 0 → -1, 1 → +1 transformation enables meaningful centroid computation
    • Clustering performed using L2 distance in the expanded dimensional space
  • Centroid Quantization: After computing float centroids in expanded space, they are converted back to binary format:

    • Centroids are stored as packed uint8_t arrays
    • KMeans (coarse) prediction is done on these quantized centroids with the BitwiseHamming distance.

3. Distance Kernels

Coarse Search (Cluster Selection)

  • Implemented specialized bitwise_hamming_distance_op for query-to-centroid distances in order to compute PairwiseDistances

Fine-Grained Search (Within Clusters)

Extended the interleaved scan kernel (ivf_flat_interleaved_scan.cuh) with specialized templates for BitwiseHamming:

  • Veclen-based optimization: Different code paths based on vectorization width

    • Veclen=16,8,4: Load data as uint32_t, use __popc(x ^ y) for 4-byte Hamming distance
    • Veclen=1,2: Byte-wise XOR and population count
  • Efficient memory access patterns:

    • Maintains interleaved data layout for coalesced memory access
    • Specialized loadAndComputeDist templates for uint8_t that leverage vectorized loads

as of 10/17/2025
Binary size increase:
branch-25.12 (CUDA 12.9 + X86): 1232.414 MB
This PR (CUDA 12.9 + X86): 1251.051 MB

@copy-pr-bot

copy-pr-bot Bot commented Jul 9, 2025

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@cjnolet cjnolet moved this from Todo to In Progress in Unstructured Data Processing Jul 11, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
cpp/src/distance/detail/fused_distance_nn/simt_kernel.cuh (1)

88-88: 💤 Low value

Redundant AccT type alias definition.

AccT is defined identically at line 88 and again at line 155. Consider removing the duplicate at line 155 since the type alias is already in scope.

♻️ Proposed fix
-    using AccT               = std::conditional_t<std::is_same_v<DataT, uint8_t>, uint32_t, DataT>;
     PairwiseDistances<DataT,
-                      AccT,  // OutT (unused in PairwiseDistances)
+                      AccT,  // OutT (unused in PairwiseDistances) - AccT defined at line 88
                       IdxT,

Also applies to: 155-155

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/distance/detail/fused_distance_nn/simt_kernel.cuh` at line 88, The
type alias AccT (defined as std::conditional_t<std::is_same_v<DataT, uint8_t>,
uint32_t, DataT>) is declared twice; remove the redundant second declaration so
only the first AccT definition remains in scope. Locate the duplicate AccT
declaration (the one identical to the existing alias) and delete it, ensuring no
other symbols (e.g., DataT) lose scope or require a re-declaration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cpp/include/cuvs/neighbors/ivf_flat.hpp`:
- Line 273: Add a complete Doxygen comment block for the public method
binary_index() describing what the method does, its return semantics (what
true/false means), that it is noexcept, and any side effects or invariants it
relies on; update the declaration bool binary_index() const noexcept; with a
Doxygen block that includes a brief description, a `@return` explaining the
boolean meaning, and notes about thread-safety or state changes if applicable to
the IVF_FLAT index class.

In `@cpp/src/cluster/detail/kmeans_balanced.cuh`:
- Around line 1176-1180: The raft::copy call that copies centers into
cluster_centers uses dim for both the source offset and length but in packed
binary mode the source mc_trainset_ccenters is stored in expanded space and must
use transformed_dim; update the offset arithmetic and copy length to use
transformed_dim (e.g., replace uses of dim in the raft::make_device_vector_view
calls with transformed_dim) so the copy uses fine_clusters_nums[i] *
transformed_dim and the start pointer uses (fine_clusters_csum[i] *
transformed_dim), ensuring mc_trainset_ccenters, fine_clusters_nums,
fine_clusters_csum, transformed_dim and cluster_centers are addressed
consistently for packed binary mode.
- Around line 516-518: The function predict uses transformed_dim but never
defines it; add a local definition named transformed_dim near the start of
predict (after line 515) that captures the post-transformation feature dimension
used by the rest of the code (the size used by transform/cur_dataset allocation
and minibatch handling). Initialize transformed_dim from the existing metadata
or helper used elsewhere in this file (for example use the transformed
feature-count accessor if one exists, or fall back to the input feature count
n_features when no transform is applied) so that calls referencing
transformed_dim (cur_dataset allocation, max_minibatch_size * transformed_dim,
and other usages) compile and use the correct dimension.

In `@cpp/src/distance/detail/fused_distance_nn/fused_bitwise_hamming_nn.cuh`:
- Around line 45-46: The min-initializer uses maxVal from DataT (uint8_t) which
is too small for accumulated BitwiseHamming distances; replace the sentinel with
the maximum value of the accumulator type (uint32_t) instead of
std::numeric_limits<DataT>::max() so that initial mins (used in functions
referenced by kv_pair_type and fused_bitwise_hamming_nn) are correct for k>31,
and update the caller-side output-buffer initialization for the BitwiseHamming
path to use the same accumulator-range sentinel (uint32_t max) so both producer
and consumer use the same range.

In `@cpp/src/neighbors/ivf_flat/ivf_flat_build.cuh`:
- Around line 228-248: The centroids_view for binary centers is created
unconditionally from index->binary_centers() even when index->binary_index() is
false; move the raft::make_device_matrix_view<const uint8_t, IdxT> construction
for centroids_view inside the if (index->binary_index()) branch and only call
cuvs::cluster::kmeans::detail::predict_bitwise_hamming(handle, batch_data_view,
centroids_view, batch_labels_view) there; leave the non-binary branch to
construct orig_centroids_view from index->centers() and call
cuvs::cluster::kmeans_balanced::predict(...) as-is to avoid creating/using an
invalid binary_centroids view.

---

Nitpick comments:
In `@cpp/src/distance/detail/fused_distance_nn/simt_kernel.cuh`:
- Line 88: The type alias AccT (defined as
std::conditional_t<std::is_same_v<DataT, uint8_t>, uint32_t, DataT>) is declared
twice; remove the redundant second declaration so only the first AccT definition
remains in scope. Locate the duplicate AccT declaration (the one identical to
the existing alias) and delete it, ensuring no other symbols (e.g., DataT) lose
scope or require a re-declaration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b0e667e0-a114-4f9a-9b44-e4171c233dbf

📥 Commits

Reviewing files that changed from the base of the PR and between caf24ce and 11e91a6.

📒 Files selected for processing (23)
  • cpp/include/cuvs/cluster/kmeans.hpp
  • cpp/include/cuvs/detail/jit_lto/ivf_flat/interleaved_scan_fragments.hpp
  • cpp/include/cuvs/neighbors/ivf_flat.hpp
  • cpp/src/cluster/detail/kmeans_balanced.cuh
  • cpp/src/cluster/kmeans_balanced.cuh
  • cpp/src/distance/detail/distance_ops/all_ops.cuh
  • cpp/src/distance/detail/distance_ops/bitwise_hamming.cuh
  • cpp/src/distance/detail/fused_distance_nn.cuh
  • cpp/src/distance/detail/fused_distance_nn/fused_bitwise_hamming_nn.cuh
  • cpp/src/distance/detail/fused_distance_nn/helper_structs.cuh
  • cpp/src/distance/detail/fused_distance_nn/simt_kernel.cuh
  • cpp/src/distance/detail/pairwise_matrix/dispatch-ext.cuh
  • cpp/src/distance/detail/pairwise_matrix/dispatch_matrix.json
  • cpp/src/distance/fused_distance_nn-inl.cuh
  • cpp/src/neighbors/detail/ann_utils.cuh
  • cpp/src/neighbors/ivf_flat/detail/jit_lto_kernels/metric_impl.cuh
  • cpp/src/neighbors/ivf_flat/detail/jit_lto_kernels/metric_matrix.json
  • cpp/src/neighbors/ivf_flat/ivf_flat_build.cuh
  • cpp/src/neighbors/ivf_flat/ivf_flat_interleaved_scan_jit.cuh
  • cpp/src/neighbors/ivf_flat/ivf_flat_search.cuh
  • cpp/src/neighbors/ivf_flat_index.cpp
  • cpp/tests/neighbors/ann_ivf_flat.cuh
  • cpp/tests/neighbors/ann_utils.cuh


void check_consistency();

bool binary_index() const noexcept;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add Doxygen docs for the new public binary_index() API.

This new public method should include a complete Doxygen block (at least behavior/return semantics) to match the header documentation standard.

📝 Proposed doc update
+  /**
+   * `@brief` Indicates whether this index is configured for binary (BitwiseHamming) mode.
+   *
+   * `@return` true if binary centers are used; false otherwise.
+   */
   bool binary_index() const noexcept;

As per coding guidelines: cpp/include/cuvs/**/*.{hpp,h}: "All public API functions must include complete Doxygen documentation describing parameters, return values, and any side effects".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bool binary_index() const noexcept;
/**
* `@brief` Indicates whether this index is configured for binary (BitwiseHamming) mode.
*
* `@return` true if binary centers are used; false otherwise.
*/
bool binary_index() const noexcept;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/include/cuvs/neighbors/ivf_flat.hpp` at line 273, Add a complete Doxygen
comment block for the public method binary_index() describing what the method
does, its return semantics (what true/false means), that it is noexcept, and any
side effects or invariants it relies on; update the declaration bool
binary_index() const noexcept; with a Doxygen block that includes a brief
description, a `@return` explaining the boolean meaning, and notes about
thread-safety or state changes if applicable to the IVF_FLAT index class.

Comment on lines +516 to +518
rmm::device_uvector<MathT> cur_dataset(
std::is_same_v<T, MathT> ? 0 : max_minibatch_size * dim, stream, mem_res);
bool need_compute_norm =
dataset_norm == nullptr && (params.metric == cuvs::distance::DistanceType::L2Expanded ||
params.metric == cuvs::distance::DistanceType::L2SqrtExpanded ||
params.metric == cuvs::distance::DistanceType::CosineExpanded);
std::is_same_v<T, MathT> ? 0 : max_minibatch_size * transformed_dim, stream, mem_res);
bool need_compute_norm = dataset_norm == nullptr &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: transformed_dim is undefined in this function.

The variable transformed_dim is used at lines 517, 529, 542, and 583, but it is never defined within the predict function. This will cause a compilation error.

🐛 Proposed fix

Add the variable definition near the start of the function (after line 515):

  auto [max_minibatch_size, _mem_per_row] = calc_minibatch_size<MathT>(
    handle, n_clusters, n_rows, dim, params.metric, std::is_same_v<T, MathT>);
+ IdxT transformed_dim = params.is_packed_binary ? dim * 8 : dim;
  rmm::device_uvector<MathT> cur_dataset(
    std::is_same_v<T, MathT> ? 0 : max_minibatch_size * transformed_dim, stream, mem_res);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
rmm::device_uvector<MathT> cur_dataset(
std::is_same_v<T, MathT> ? 0 : max_minibatch_size * dim, stream, mem_res);
bool need_compute_norm =
dataset_norm == nullptr && (params.metric == cuvs::distance::DistanceType::L2Expanded ||
params.metric == cuvs::distance::DistanceType::L2SqrtExpanded ||
params.metric == cuvs::distance::DistanceType::CosineExpanded);
std::is_same_v<T, MathT> ? 0 : max_minibatch_size * transformed_dim, stream, mem_res);
bool need_compute_norm = dataset_norm == nullptr &&
IdxT transformed_dim = params.is_packed_binary ? dim * 8 : dim;
rmm::device_uvector<MathT> cur_dataset(
std::is_same_v<T, MathT> ? 0 : max_minibatch_size * transformed_dim, stream, mem_res);
bool need_compute_norm = dataset_norm == nullptr &&
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/cluster/detail/kmeans_balanced.cuh` around lines 516 - 518, The
function predict uses transformed_dim but never defines it; add a local
definition named transformed_dim near the start of predict (after line 515) that
captures the post-transformation feature dimension used by the rest of the code
(the size used by transform/cur_dataset allocation and minibatch handling).
Initialize transformed_dim from the existing metadata or helper used elsewhere
in this file (for example use the transformed feature-count accessor if one
exists, or fall back to the input feature count n_features when no transform is
applied) so that calls referencing transformed_dim (cur_dataset allocation,
max_minibatch_size * transformed_dim, and other usages) compile and use the
correct dimension.

Comment on lines +1176 to +1180
raft::copy(handle,
raft::make_device_vector_view(cluster_centers + (dim * fine_clusters_csum[i]),
fine_clusters_nums[i] * dim),
raft::make_device_vector_view<const MathT>(mc_trainset_ccenters.data(),
fine_clusters_nums[i] * dim));
raft::make_device_vector_view(cluster_centers + (dim * fine_clusters_csum[i]),
fine_clusters_nums[i] * dim),
raft::make_device_vector_view<const MathT>(mc_trainset_ccenters.data(),
fine_clusters_nums[i] * dim));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Incorrect copy size for packed binary mode.

For packed binary mode, mc_trainset_ccenters contains centers in expanded space (fine_clusters_nums_max * transformed_dim elements, per line 1084). However, the copy uses dim instead of transformed_dim for both the offset and size, which will copy the wrong amount of data and corrupt the output.

🐛 Proposed fix
-    raft::copy(handle,
-      raft::make_device_vector_view(cluster_centers + (dim * fine_clusters_csum[i]),
-                                    fine_clusters_nums[i] * dim),
-      raft::make_device_vector_view<const MathT>(mc_trainset_ccenters.data(),
-                                                 fine_clusters_nums[i] * dim));
+    IdxT centers_stride = params.is_packed_binary ? transformed_dim : dim;
+    raft::copy(handle,
+      raft::make_device_vector_view(cluster_centers + (centers_stride * fine_clusters_csum[i]),
+                                    fine_clusters_nums[i] * centers_stride),
+      raft::make_device_vector_view<const MathT>(mc_trainset_ccenters.data(),
+                                                 fine_clusters_nums[i] * centers_stride));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
raft::copy(handle,
raft::make_device_vector_view(cluster_centers + (dim * fine_clusters_csum[i]),
fine_clusters_nums[i] * dim),
raft::make_device_vector_view<const MathT>(mc_trainset_ccenters.data(),
fine_clusters_nums[i] * dim));
raft::make_device_vector_view(cluster_centers + (dim * fine_clusters_csum[i]),
fine_clusters_nums[i] * dim),
raft::make_device_vector_view<const MathT>(mc_trainset_ccenters.data(),
fine_clusters_nums[i] * dim));
IdxT centers_stride = params.is_packed_binary ? transformed_dim : dim;
raft::copy(handle,
raft::make_device_vector_view(cluster_centers + (centers_stride * fine_clusters_csum[i]),
fine_clusters_nums[i] * centers_stride),
raft::make_device_vector_view<const MathT>(mc_trainset_ccenters.data(),
fine_clusters_nums[i] * centers_stride));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/cluster/detail/kmeans_balanced.cuh` around lines 1176 - 1180, The
raft::copy call that copies centers into cluster_centers uses dim for both the
source offset and length but in packed binary mode the source
mc_trainset_ccenters is stored in expanded space and must use transformed_dim;
update the offset arithmetic and copy length to use transformed_dim (e.g.,
replace uses of dim in the raft::make_device_vector_view calls with
transformed_dim) so the copy uses fine_clusters_nums[i] * transformed_dim and
the start pointer uses (fine_clusters_csum[i] * transformed_dim), ensuring
mc_trainset_ccenters, fine_clusters_nums, fine_clusters_csum, transformed_dim
and cluster_centers are addressed consistently for packed binary mode.

Comment on lines +45 to +46
constexpr auto maxVal = std::numeric_limits<DataT>::max();
using kv_pair_type = raft::KeyValuePair<IdxT, uint32_t>;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Use an accumulator-range sentinel for min initialization.

maxVal is derived from DataT (uint8_t), so it initializes to 255. Bitwise Hamming here accumulates into uint32_t; for k > 31, true distances can exceed 255, causing incorrect min selection.

Suggested fix
-  constexpr auto maxVal  = std::numeric_limits<DataT>::max();
+  constexpr uint32_t maxVal = std::numeric_limits<uint32_t>::max();

Please also align the caller-side output-buffer initialization for the BitwiseHamming path to the same range.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
constexpr auto maxVal = std::numeric_limits<DataT>::max();
using kv_pair_type = raft::KeyValuePair<IdxT, uint32_t>;
constexpr uint32_t maxVal = std::numeric_limits<uint32_t>::max();
using kv_pair_type = raft::KeyValuePair<IdxT, uint32_t>;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/distance/detail/fused_distance_nn/fused_bitwise_hamming_nn.cuh`
around lines 45 - 46, The min-initializer uses maxVal from DataT (uint8_t) which
is too small for accumulated BitwiseHamming distances; replace the sentinel with
the maximum value of the accumulator type (uint32_t) instead of
std::numeric_limits<DataT>::max() so that initial mins (used in functions
referenced by kv_pair_type and fused_bitwise_hamming_nn) are correct for k>31,
and update the caller-side output-buffer initialization for the BitwiseHamming
path to use the same accumulator-range sentinel (uint32_t max) so both producer
and consumer use the same range.

Comment on lines +228 to +248
auto centroids_view = raft::make_device_matrix_view<const uint8_t, IdxT>(
index->binary_centers().data_handle(), n_lists, dim);

if (index->binary_index()) {
if constexpr (std::is_same_v<T, uint8_t>) {
cuvs::cluster::kmeans::detail::predict_bitwise_hamming(
handle, batch_data_view, centroids_view, batch_labels_view);
} else {
RAFT_FAIL("BitwiseHamming distance is only supported with uint8_t data type, got %s",
typeid(T).name());
}
} else {
auto orig_centroids_view = raft::make_device_matrix_view<const float, IdxT>(
index->centers().data_handle(), n_lists, dim);
cuvs::cluster::kmeans_balanced::predict(handle,
kmeans_params,
batch_data_view,
orig_centroids_view,
batch_labels_view,
utils::mapping<float>{});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Move binary centroids view construction inside the conditional block.

centroids_view is created from binary_centers() at lines 228-229 before checking index->binary_index(). For non-binary indexes, accessing binary_centers() may return an uninitialized or empty view. The view should be created only when needed.

🐛 Proposed fix
-    auto centroids_view = raft::make_device_matrix_view<const uint8_t, IdxT>(
-      index->binary_centers().data_handle(), n_lists, dim);
-
     if (index->binary_index()) {
       if constexpr (std::is_same_v<T, uint8_t>) {
+        auto centroids_view = raft::make_device_matrix_view<const uint8_t, IdxT>(
+          index->binary_centers().data_handle(), n_lists, dim);
         cuvs::cluster::kmeans::detail::predict_bitwise_hamming(
           handle, batch_data_view, centroids_view, batch_labels_view);
       } else {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
auto centroids_view = raft::make_device_matrix_view<const uint8_t, IdxT>(
index->binary_centers().data_handle(), n_lists, dim);
if (index->binary_index()) {
if constexpr (std::is_same_v<T, uint8_t>) {
cuvs::cluster::kmeans::detail::predict_bitwise_hamming(
handle, batch_data_view, centroids_view, batch_labels_view);
} else {
RAFT_FAIL("BitwiseHamming distance is only supported with uint8_t data type, got %s",
typeid(T).name());
}
} else {
auto orig_centroids_view = raft::make_device_matrix_view<const float, IdxT>(
index->centers().data_handle(), n_lists, dim);
cuvs::cluster::kmeans_balanced::predict(handle,
kmeans_params,
batch_data_view,
orig_centroids_view,
batch_labels_view,
utils::mapping<float>{});
}
if (index->binary_index()) {
if constexpr (std::is_same_v<T, uint8_t>) {
auto centroids_view = raft::make_device_matrix_view<const uint8_t, IdxT>(
index->binary_centers().data_handle(), n_lists, dim);
cuvs::cluster::kmeans::detail::predict_bitwise_hamming(
handle, batch_data_view, centroids_view, batch_labels_view);
} else {
RAFT_FAIL("BitwiseHamming distance is only supported with uint8_t data type, got %s",
typeid(T).name());
}
} else {
auto orig_centroids_view = raft::make_device_matrix_view<const float, IdxT>(
index->centers().data_handle(), n_lists, dim);
cuvs::cluster::kmeans_balanced::predict(handle,
kmeans_params,
batch_data_view,
orig_centroids_view,
batch_labels_view,
utils::mapping<float>{});
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/neighbors/ivf_flat/ivf_flat_build.cuh` around lines 228 - 248, The
centroids_view for binary centers is created unconditionally from
index->binary_centers() even when index->binary_index() is false; move the
raft::make_device_matrix_view<const uint8_t, IdxT> construction for
centroids_view inside the if (index->binary_index()) branch and only call
cuvs::cluster::kmeans::detail::predict_bitwise_hamming(handle, batch_data_view,
centroids_view, batch_labels_view) there; leave the non-binary branch to
construct orig_centroids_view from index->centers() and call
cuvs::cluster::kmeans_balanced::predict(...) as-is to avoid creating/using an
invalid binary_centroids view.

@tarang-jain
tarang-jain requested review from a team as code owners October 1, 2026 03:59
@tarang-jain

Copy link
Copy Markdown
Contributor Author

/ok to test 7f27206

@copy-pr-bot

copy-pr-bot Bot commented Oct 1, 2026

Copy link
Copy Markdown

/ok to test 7f27206

@tarang-jain, there was an error processing your request: E2

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/2/

@tarang-jain

Copy link
Copy Markdown
Contributor Author

/ok to test 7f27206

@copy-pr-bot

copy-pr-bot Bot commented Oct 1, 2026

Copy link
Copy Markdown

/ok to test 7f27206

@tarang-jain, there was an error processing your request: E2

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/2/

@tarang-jain

Copy link
Copy Markdown
Contributor Author

/ok to test 7f27206

@tarang-jain

Copy link
Copy Markdown
Contributor Author

/ok to test 1b94be6

@copy-pr-bot

copy-pr-bot Bot commented Oct 2, 2026

Copy link
Copy Markdown

/ok to test 759f6e2

@tarang-jain, there was an error processing your request: E2

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/2/

@tarang-jain

Copy link
Copy Markdown
Contributor Author

/ok to test 759f6e2

@tarang-jain

Copy link
Copy Markdown
Contributor Author

/ok to test ec879d9

@copy-pr-bot

copy-pr-bot Bot commented Oct 3, 2026

Copy link
Copy Markdown

/ok to test ec879d9

@tarang-jain, there was an error processing your request: E2

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/2/

@tarang-jain

Copy link
Copy Markdown
Contributor Author

/ok to test ec879d9

@copy-pr-bot

copy-pr-bot Bot commented Oct 3, 2026

Copy link
Copy Markdown

/ok to test ec879d9

@tarang-jain, there was an error processing your request: E2

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/2/

@tarang-jain

Copy link
Copy Markdown
Contributor Author

/ok to test ec879d9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cpp feature request New feature or request non-breaking Introduces a non-breaking change stale-active

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

6 participants