Skip to content

[BUG] single_linkage aborts on unsupported DistanceType instead of rejecting it #8497

Description

@irina-resh-nvda

single_linkage aborts on unsupported DistanceType instead of rejecting it

Summary

ML::linkage::single_linkage forwards its DistanceType argument to cuvs without validation. cuvs only supports L2Expanded and L2SqrtExpanded on that path, so any other value surfaces as an uncaught raft::logic_error and std::terminate from inside libcuvs rather than an error at the call site.

sg_benchmark hits this: cpp/bench/sg/linkage.cu:42 passes ML::distance::DistanceType::L2Unexpanded, so the Linkage benchmark aborts.

Environment

  • cuML: branch-26.08 (26.08.00), commit 133c6e294
  • cuVS / RAFT / RMM / CCCL: 26.08.00, built from source
  • CUDA: (internal)
  • GPU / arch: Vera Rubin GR100 (probably platform independent)
  • OS / arch: Ubuntu 24.04.4 LTS 7.0.0-2012-nvidia-bos-64k aarch64
  • Compiler: g++ (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0

Reproducer

./build.sh libcuml bench -n
./cpp/build/bench/sg_benchmark --benchmark_filter='Linkage'

Output

terminate called after throwing an instance of 'raft::logic_error'
  what():  RAFT failure at file=.../cuvs/cpp/src/cluster/detail/kmeans_common.cuh line=343:
           kmeans requires L2Expanded or L2SqrtExpanded distance, have 4
...
#5 in libcuvs.so: cuvs::cluster::agglomerative::single_linkage(...)
#6 in libcuml.so: ML::linkage::single_linkage(raft::handle_t const&, float const*, int, int,
     unsigned long, ML::distance::DistanceType, int*, int*, bool, int) +0x94
#7 in ./bench/sg_benchmark
...
Aborted (core dumped)

Metric 4 is L2Unexpanded (cpp/include/cuml/common/distance_type.hpp:18). The check that fails is cuvs/cpp/src/cluster/detail/kmeans_common.cuh:335-344, reached through the agglomerative KNN path.

Problems

The benchmark passes a metric that is not supported. Fix:

--- a/cpp/bench/sg/linkage.cu
+++ b/cpp/bench/sg/linkage.cu
@@
-                                  ML::distance::DistanceType::L2Unexpanded,
+                                  ML::distance::DistanceType::L2SqrtExpanded,

More importantly, ML::linkage::single_linkage accepts any DistanceType and aborts the process for unsupported values. It should validate the metric and throw a cuml exception at the API boundary, or document and enforce the supported set. Any caller passing L2Unexpanded today gets std::terminate.

Whether the Python AgglomerativeClustering wrapper can reach the same path with a non-expanded metric has not been checked; if it can, this is user-visible rather than benchmark-only.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ? - Needs TriageNeed team to review and classifybugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions