Skip to main content

Vector Inputs

All eight cuVS UDTFs take relation arguments as parenthesized SELECT subqueries. Each subquery remains a planner child. For gpu_validate_call, register a table or view with the same schema. Metadata validation does not evaluate rows.

Relation identity​

Every dataset, queries, x, y, or input binding names a logical ID column:

  • The ID must be Int32, Int64, Utf8, LargeUtf8, or Utf8View, and no ID may be null.
  • IDs may repeat. Result ordinals disambiguate physical rows with equal IDs.
  • A subquery's top-level ORDER BY fixes the order its rows are numbered in. Sort keys must be output columns of the subquery, by name or 1-based position. Other keys are rejected with input_ordering_key_not_projected unless LIMIT, OFFSET, or FETCH bounds the rows. Without a top-level ORDER BY, row order is unspecified, and rows that tie on every key have no stable order.
  • The ID comes from a relation field. Name the field in each JSON binding with "id". cuVS does not assign a logical ID from row position.

Dense-vector binding shapes​

Each binding chooses one vector shape. Feature order defines dimension order. A SQL call infers the binding from the subquery's field types. When the only field besides id is a FixedSizeList, List, or LargeList, that field is the list column, whatever its name. Otherwise every field besides id is a wide feature column. A list field next to other feature fields is rejected with list_vector_with_additional_features.

Wide columns​

{"id":"paper_id","vector":{"columns":["d0","d1","d2"]}}
  • columns contains at least one unique, non-empty column name.
  • Each selected feature column holds no null values. All columns in the binding share one supported element type.
  • The listed order defines the vector dimensions.

One list column​

{"id":"paper_id","vector":{"column":"embedding"}}
  • embedding is FixedSizeList<T, D>, List<T>, or LargeList<T> with a supported element type T, and no row of it is null.
  • List elements hold no null values. FixedSizeList has a positive dimension D.
  • Variable-width List and LargeList rows must have one uniform, positive dimension after evaluation.

Relation size​

cuDF indexes the values of a list column with 32-bit offsets. One relation argument can therefore hold at most 2,147,483,647 list values in its vector column, which is 1,048,575 rows of a 2048-dimension FixedSizeList. The same limit applies to each intermediate result inside the subquery. Separate scalar feature columns hold up to 2,147,483,647 rows each.

A subquery may scan and filter a larger Parquet file. The source planner reads it in parts that each stay under the limit, sized from the footer's value counts or, without a footer, from fixed list widths, and only the rows the subquery returns count toward the relation. A relation above the limit fails the query with size_overflow. The message names the column, its value count and the row count that fits at its width. Filter the subquery to fewer rows, or split the dataset into row ranges, run one call per range and combine the results with UNION ALL. For brute-force kNN over a split dataset, keep the k smallest distances per query across the parts.

Null values​

Schema nullability does not matter. A nullable field type is accepted for the ID, for every feature column, and for a list column and its elements. Results of aggregates, Parquet columns, and lists built in SQL therefore need no rewrite. The contract applies to values. A null ID, a null feature value, a null list row, or a null list element fails the query with an invalid-input error (rapids_invalid_input) that names the function, the relation role, and the column. gpu_validate_call reads no values and cannot find nulls.

Add COALESCE(column, CAST(0 AS REAL)) only when the data contains nulls and a fallback value is correct, or drop the offending rows with WHERE column IS NOT NULL.

A list vector built in SQL with ARRAY_AGG, MAKE_ARRAY, or COALESCE(..., ARRAY_REPEAT(...)) is computed by DataFusion on the CPU, because native lowering does not build lists. Its result is uploaded as the relation and accepted when it contains no null rows or elements.

Element types​

Floating vector values must be finite. NaN and infinity are rejected. Integer elements have no finiteness requirement. All vector bindings in one call share an element type and dimension. cuVS does not cast vector elements implicitly. Use CAST in a relation subquery to select a supported type. Float16 is unsupported because cuDF has no Float16 representation.

Vector element and metric support by UDTF​

Each cell lists valid metric values for that input element. Yes means the element is supported without a metric option; No means the element is unsupported.

UDTFFloat32Float64Int8UInt8
cuvs_brute_force_knnl2_expanded, l2_sqrt_expanded, cosine, inner_productNoNoNo
cuvs_cagral2_expanded, inner_product, cosineNol2_expanded, inner_product, cosinel2_expanded, inner_product, cosine
cuvs_ivf_flatl2_expanded, l2_sqrt_expanded, cosine, inner_productNol2_expanded, l2_sqrt_expanded, cosine, inner_productl2_expanded, l2_sqrt_expanded, cosine, inner_product
cuvs_ivf_pql2_expanded, l2_sqrt_expanded, cosine, inner_productNol2_expanded, l2_sqrt_expanded, inner_productl2_expanded, l2_sqrt_expanded, inner_product
cuvs_kmeansl2_expanded, l2_sqrt_expandedl2_expanded, l2_sqrt_expandedNoNo
cuvs_pairwise_distancel2_expanded, l2_sqrt_expanded, cosine, inner_productl2_expanded, l2_sqrt_expanded, cosine, inner_productNoNo
cuvs_pcaYesNoNoNo
cuvs_top_kYesNoNoNo

Brute-force kNN and the three ANN UDTFs return Float32 distance values. Pairwise distance follows the input float width (Float32 or Float64). KMeans cluster_id remains Int32.

Float32 expanded squared L2 evaluates ||x||² + ||y||² - 2 x·y. Roundoff and cancellation near zero can produce a small positive distance even for identical vectors; negative roundoff is clamped to zero. Positive distances are retained. Equal rounded norms do not establish vector equality. Near-tied distances can change neighbor selection at the k boundary, and the returned IDs may differ between distance implementations. The API specifies no fixed numerical tolerance or bit-exact zero for arbitrary Float32 inputs.

What validation can prove​

gpu_validate_call checks the JSON envelope, relation existence, field names, static types, binding shapes, duplicate wide-column names, matching element types, valid element/metric pairs, and scalar option ranges. It does not evaluate subqueries, scan values, or launch cuVS. Known relation cardinalities and fixed-size dimensions may also be checked during SQL planning. The following constraints are checked against evaluated rows when those facts are not known statically:

OperationEvaluated-relation requirements
Brute-force kNNDataset must be non-empty. k cannot exceed dataset rows. Dataset and query dimensions must match. Empty queries may produce an empty result with the declared schema.
IVF-FlatDataset must be non-empty. k and n_lists cannot exceed dataset rows. Cosine requires at least two dimensions. With incomplete probes, fewer than k neighbors may be returned.
IVF-PQDataset must be non-empty. k and n_lists cannot exceed dataset rows. Cosine requires at least two dimensions. Compression can omit neighbors even when all lists are probed.
CAGRADataset must be non-empty. k and graph degrees are constrained by dataset rows. Search may omit missing neighbors.
Pairwise distanceEmpty x or y returns an empty result with the declared schema. Output rows equal x rows multiplied by y rows and are bounded by the query allocation cap.
Vector Top-Kk cannot exceed vector dimension. For variable-width lists, that dimension is checked after evaluation. Empty input returns an empty result.
KMeansInput must be non-empty. n_clusters cannot exceed evaluated input rows.
PCAInput needs at least two rows and two dimensions. n_components cannot exceed evaluated dimension.

Scalar checks do not require evaluated rows: IVF search requires n_probes <= n_lists; CAGRA requires k <= itopk_size and intermediate_graph_degree > graph_degree. CAGRA also rejects cosine with nn_descent, and single_cta requires itopk_size <= 1024. A nonzero IVF-PQ pq_dim * pq_bits must be divisible by 8.

cuVS calls execute inside the admitted query memory domain. Allocation beyond the configured cap fails at the allocator. See Integration for embedded and Flight SQL setup.