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.
single_linkage aborts on unsupported DistanceType instead of rejecting it
Summary
ML::linkage::single_linkageforwards itsDistanceTypeargument to cuvs without validation. cuvs only supportsL2ExpandedandL2SqrtExpandedon that path, so any other value surfaces as an uncaughtraft::logic_errorandstd::terminatefrom inside libcuvs rather than an error at the call site.sg_benchmarkhits this:cpp/bench/sg/linkage.cu:42passesML::distance::DistanceType::L2Unexpanded, so theLinkagebenchmark aborts.Environment
133c6e294Reproducer
Output
Metric 4 is
L2Unexpanded(cpp/include/cuml/common/distance_type.hpp:18). The check that fails iscuvs/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:
More importantly,
ML::linkage::single_linkageaccepts anyDistanceTypeand aborts the process for unsupported values. It should validate the metric and throw acumlexception at the API boundary, or document and enforce the supported set. Any caller passingL2Unexpandedtoday getsstd::terminate.Whether the Python
AgglomerativeClusteringwrapper 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.