@@ -22,20 +22,16 @@ use arrow_array::builder::UInt32Builder;
2222use arrow_array:: types:: { Float16Type , Float32Type , Float64Type } ;
2323use arrow_array:: UInt64Array ;
2424use arrow_array:: {
25- cast:: AsArray , types:: UInt32Type , Array , FixedSizeListArray , Float32Array , RecordBatch ,
26- UInt32Array ,
25+ cast:: AsArray , types:: UInt32Type , Array , FixedSizeListArray , RecordBatch , UInt32Array ,
2726} ;
28- use arrow_ord:: sort:: sort_to_indices;
2927use arrow_schema:: { DataType , Field } ;
3028use arrow_select:: take:: take;
3129use async_trait:: async_trait;
32- use futures:: { stream, StreamExt , TryStreamExt } ;
30+ use futures:: { stream, StreamExt } ;
3331use lance_arrow:: * ;
3432use lance_core:: { Error , Result , ROW_ID } ;
3533use lance_linalg:: {
36- distance:: {
37- cosine_distance_batch, dot_distance_batch, l2_distance_batch, Cosine , Dot , MetricType , L2 ,
38- } ,
34+ distance:: { Cosine , Dot , MetricType , L2 } ,
3935 MatrixView ,
4036} ;
4137use log:: { debug, info} ;
@@ -51,6 +47,7 @@ use crate::vector::{
5147 transform:: Transformer ,
5248} ;
5349pub use builder:: IvfBuildParams ;
50+ use lance_linalg:: kmeans:: KMeans ;
5451
5552fn new_ivf_impl < T : ArrowFloatType + Dot + Cosine + L2 + ' static > (
5653 centroids : & T :: ArrayType ,
@@ -349,23 +346,22 @@ impl<T: ArrowFloatType + Dot + L2 + Cosine + 'static> IvfImpl<T> {
349346 // wouldn't cover all rows but 13-element chunks (13 * 32 = 416) would
350347 // have one empty chunk at the end. This filter removes those empty chunks.
351348 . filter ( |range| futures:: future:: ready ( range. start < range. end ) )
352- . map ( |range| {
349+ . map ( |range| async {
353350 let centroids = centroids. clone ( ) ;
354351 let data = data. clone ( ) ;
355- tokio:: task:: spawn_blocking ( move || {
356- compute_partitions :: < T > (
357- centroids. as_slice ( ) ,
358- & data. as_slice ( ) [ range] ,
359- dimension,
360- metric_type,
361- )
362- } )
352+
353+ compute_partitions :: < T > (
354+ centroids. as_slice ( ) ,
355+ & data. as_slice ( ) [ range] ,
356+ dimension,
357+ metric_type,
358+ )
363359 . in_current_span ( )
360+ . await
364361 } )
365362 . buffered ( chunks)
366- . try_collect ( )
367- . await
368- . expect ( "compute_partitions: schedule CPU task" ) ;
363+ . collect :: < Vec < _ > > ( )
364+ . await ;
369365
370366 UInt32Array :: from_iter ( result. iter ( ) . flatten ( ) . copied ( ) )
371367 }
@@ -428,16 +424,6 @@ impl<T: ArrowFloatType + Dot + L2 + Cosine + 'static> Ivf for IvfImpl<T> {
428424 }
429425
430426 fn find_partitions ( & self , query : & dyn Array , nprobes : usize ) -> Result < UInt32Array > {
431- if query. len ( ) != self . dimension ( ) {
432- return Err ( Error :: IO {
433- message : format ! (
434- "Ivf::find_partition: dimension mismatch: {} != {}" ,
435- query. len( ) ,
436- self . dimension( )
437- ) ,
438- location : location ! ( ) ,
439- } ) ;
440- }
441427 let query = query
442428 . as_any ( )
443429 . downcast_ref :: < T :: ArrayType > ( )
@@ -449,23 +435,13 @@ impl<T: ArrowFloatType + Dot + L2 + Cosine + 'static> Ivf for IvfImpl<T> {
449435 ) ,
450436 location : Default :: default ( ) ,
451437 } ) ?;
452- let centroid_values = self . centroids . data ( ) ;
453- let centroids = centroid_values. as_slice ( ) ;
454- let dim = query. len ( ) ;
455- let distances = Float32Array :: from_iter_values ( match self . metric_type {
456- lance_linalg:: distance:: DistanceType :: L2 => {
457- l2_distance_batch ( query. as_slice ( ) , centroids, dim)
458- }
459- lance_linalg:: distance:: DistanceType :: Cosine => {
460- cosine_distance_batch ( query. as_slice ( ) , centroids, dim)
461- }
462- lance_linalg:: distance:: DistanceType :: Dot => {
463- dot_distance_batch ( query. as_slice ( ) , centroids, dim)
464- }
465- } ) ;
466-
467- let top_k_partitions = sort_to_indices ( & distances, None , Some ( nprobes) ) ?;
468- Ok ( top_k_partitions)
438+ // TODO: hold kmeans in this struct.
439+ let kmeans = KMeans :: < T > :: with_centroids (
440+ self . centroids . data ( ) . clone ( ) ,
441+ self . dimension ( ) ,
442+ self . metric_type ,
443+ ) ;
444+ Ok ( kmeans. find_partitions ( query. as_slice ( ) , nprobes) ?)
469445 }
470446
471447 async fn partition_transform ( & self , batch : & RecordBatch , column : & str ) -> Result < RecordBatch > {
0 commit comments