Mojo · Linear Algebra

Linear Algebra

from usearch import DenseSoftmaxState, DenseProducts, DenseMaxsimConfig, … 3.0.0-rc.1 · 4c3e5023

§ Sparse Multiplication

multiply is a sparse matrix product: every pair the walk scored for each left row, in traversal order, lands in an arena as one ragged run, with one more offset than left rows, as Apache Arrow lays a ragged batch out.

var products = index.on(executor).multiply(left, arena, DenseMultiplyConfig(wanted=64))
var offsets = products.offsets()
for row in range(left_rows):
    print(row, Int(offsets[row + 1] - offsets[row]), "pairs")

§ Late Interaction

maxsim is late interaction: every query row takes its best match within a key, and those maxima sum to that key’s score. A document is one key holding its token rows, which is what a values_per_key above one exists for, and the wanted count is over documents rather than rows. The keys land as multiply’s pairs do, query i spanning offsets()[i] up to offsets()[i + 1], largest score first, and a zero wanted keeps every key a query scored.

var documents = index.on(executor).maxsim(tokens, tokens_per_query, 10, arena)  # DenseProducts, as multiply answers
var offsets = documents.offsets()
for query in range(documents.queries):
    print(query, Int(offsets[query + 1] - offsets[query]), "documents")

§ Attention

attend is Flash Attention folded into the walk: every key it scores folds into each head’s running maximum, partition and weighted value sum, with no top-k cut, and the attended rows land in the arena already divided by the partition. The index stores no values, so a ValueLookup resolves every scored batch of keys to value rows, columns values of scalar apiece, the index’s own width and kind, which it checks before answering any row. A key without a row refuses the call with Status.SHAPE_MISMATCH, since a missing row is a wrong softmax rather than a smaller one. A VRAM index calls its lookup inside the device walk, so there value_lookup must be a __device__ function’s address, read with cudaMemcpyFromSymbol on NVIDIA or hipMemcpyFromSymbol on AMD; a host function there is undefined, never refused.

def value_rows(
    state: Address, keys: Pointer[Key, ImmUntrackedOrigin], count: c_size_t,
    scalar: ScalarKind, columns: c_size_t, rows: Pointer[Address, MutAnyOrigin],
) abi("C"):
    ...  # write one row address per key, or NULL_ADDRESS when it has none

var carry = List[DenseSoftmaxState](length=queries_count, fill=DenseSoftmaxState())
var context = index.on(executor).attend[DType.float32](
    queries, value_rows, cache_address, arena, DenseAttendConfig(head_count=8, carry=carry)
)

With head_count=8, row t * 8 + h of the queries is head h of token t, and the heads of one token share its walk. A carry of one DenseSoftmaxState per query row, lent by you, folds this branch into another over the same queries, such as a recent window kept out of the index; a shorter one is refused, since the C structure carries no count for it.

API

Types

ValueLookupusearch_value_lookup_t: resolves count keys to one value-row address each, columns values of scalar apiece - the index's own width and kind - alive until the call returns; a NULL_ADDRESS row refuses the call.
comptime ValueLookup = def(
    Int,
    Pointer[Key, ImmUntrackedOrigin],
    UInt,
    ScalarKind,
    UInt,
    Pointer[Int, MutAnyOrigin]
) abi("C") thin -> None

Called with the value_lookup_state the verb was handed, once per scored batch and concurrently from the executor's threads. A lookup whose rows hold another kind or width answers NULL_ADDRESS for every key rather than handing the engine rows it would misread.

A VRAM index calls it inside the device walk instead, so there it must be the address of a __device__ function, as cudaMemcpyFromSymbol reads it, with its state and rows in memory that device reads. Nothing tells the two kinds apart, so a host function there is undefined, never refused.

StructDenseSoftmaxStateThe online-softmax carry of one query row - usearch_dense_softmax_state_t.1
struct DenseSoftmaxState

Flash Attention's running maximum and partition. The two are one concept: a maximum without its partition is a number nothing can rescale, so they share an element rather than travelling as two runs a caller could supply half of. Carrying them folds one attention call into another over the same queries.

Fields

maximum_scoreFloat32The largest logit seen so far - the recurrence's m.
partitionFloat32The sum of exponentials taken against that maximum - the recurrence's l.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable, RegisterPassable, TrivialRegisterPassable
__init__Zeroes both, which is what an unfolded first branch starts from.
def __init__() -> Self
StructDenseProductsThe ragged output of multiply and maxsim - usearch_matches_tape_view_t - read in place from its arena: query i spans pairs offsets()[i] up to offsets()[i + 1] of keys() and scores().3
struct DenseProducts[origin: MutOrigin]

Parameters

originMutOrigincomptimeThe arena the pairs live in, which this result borrows.

Fields

arenaPointer[Arena, origin]The arena holding the pairs.
generationIntThe arena's call these pairs came from, so a read after a later call is refused.
viewMatchesTapeViewArgumentsThe keys, products and offsets, as the engine wrote them.
queriesIntLeft-hand rows the call multiplied, or queries it scored.
pairsIntPairs written across every query.
requiredIntPairs the walks scored, or keys the queries scored for maxsim, before wanted cut any; above pairs means some lists were truncated.

Conforms to

Deinitable, Movable
offsetsOne more offset than queries, as Apache Arrow lays a ragged batch out.
def offsets(ref self) -> Span[UInt, origin_of(self)]

Returns

The offsets into keys() and scores(), borrowed from the arena this result reads.

Raises

Error with UNINITIALIZED once a later call rewound the arena, or DEVICE over VRAM.
keysEach pair's indexed entry, borrowed from the arena this result reads.
def keys(ref self) -> Span[Key, origin_of(self)]

Returns

One key per pair.

Raises

Error with UNINITIALIZED once a later call rewound the arena, or DEVICE over VRAM.
scoresEach pair's product, positionally paired with keys().
def scores(ref self) -> Span[Float64, origin_of(self)]

Returns

One score per pair.

Raises

Error with UNINITIALIZED once a later call rewound the arena, or DEVICE over VRAM.
StructDenseMaxsimConfigThe knobs of usearch_dense_maxsim_t; zeroed or absent ones derive what the C interface derives.1
struct DenseMaxsimConfig[stats_origin: MutOrigin = MutUntrackedOrigin]

Parameters

stats_originMutOrigincomptimeThe lent telemetry slot's origin, inferred where one is lent.

Fields

expansion_factorIntThe breadth of the candidates; zero derives.
statsOptional[Pointer[DenseTraversalStats, stats_origin]]Receives this call's traversal telemetry, fully overwritten; absent skips reporting.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable
__init__Names only the knobs that differ from the derived ones.
def __init__(
    out self,
    *,
    expansion_factor: Int = Int(0),
    stats: Optional[Pointer[DenseTraversalStats, stats_origin]] = Optional()
)

Parameters

expansion_factorIntThe breadth of the candidates; zero derives.
statsOptional[Pointer[DenseTraversalStats, stats_origin]]Receives this call's traversal telemetry; absent skips reporting.
StructDenseMultiplyConfigThe knobs of usearch_dense_multiply_t; zeroed or absent ones derive what the C interface derives.1
struct DenseMultiplyConfig[stats_origin: MutOrigin = MutUntrackedOrigin]

Parameters

stats_originMutOrigincomptimeThe lent telemetry slot's origin, inferred where one is lent.

Fields

wantedIntPairs kept per left row, the first ones its walk scored; zero keeps every pair.
expansion_factorIntThe breadth of the candidates, which widens the emitted pattern; zero derives.
statsOptional[Pointer[DenseTraversalStats, stats_origin]]Receives this call's traversal telemetry, fully overwritten; absent skips reporting.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable
__init__Names only the knobs that differ from the derived ones.
def __init__(
    out self,
    *,
    wanted: Int = Int(0),
    expansion_factor: Int = Int(0),
    stats: Optional[Pointer[DenseTraversalStats, stats_origin]] = Optional()
)

Parameters

wantedIntPairs kept per left row, the first ones its walk scored; zero keeps every pair.
expansion_factorIntThe breadth of the candidates, which widens the emitted pattern; zero derives.
statsOptional[Pointer[DenseTraversalStats, stats_origin]]Receives this call's traversal telemetry; absent skips reporting.
StructDenseAttendConfigThe knobs of usearch_dense_attend_t; zeroed or absent ones derive what the C interface derives.1
struct DenseAttendConfig[carry_origin: MutOrigin = MutUntrackedOrigin, stats_origin: MutOrigin = MutUntrackedOrigin]

Parameters

carry_originMutOrigincomptimeThe lent softmax states' origin, inferred where any are lent.
stats_originMutOrigincomptimeThe lent telemetry slot's origin, inferred where one is lent.

Fields

head_countIntThe query heads sharing the index's key-value head; it must divide the rows, and zero means one.
carrySpan[DenseSoftmaxState, carry_origin]The softmax states, one per query row; empty skips them.
expansion_factorIntThe breadth of the candidates; zero derives. Wider candidates walk further, folding more of the tail.
score_scaleFloat32The logit scale, conventionally the inverse square root of the head width; zero derives it.
statsOptional[Pointer[DenseTraversalStats, stats_origin]]Receives this call's traversal telemetry, fully overwritten; absent skips reporting.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable
__init__Names only the knobs that differ from the derived ones.
def __init__(
    out self,
    *,
    head_count: Int = Int(0),
    carry: Span[DenseSoftmaxState, carry_origin] = Span(),
    expansion_factor: Int = Int(0),
    score_scale: Float32 = Float32("0"),
    stats: Optional[Pointer[DenseTraversalStats, stats_origin]] = Optional()
)

Parameters

head_countIntThe query heads sharing the index's key-value head; zero means one.
carrySpan[DenseSoftmaxState, carry_origin]The softmax states, one per query row; empty skips them.
expansion_factorIntThe breadth of the candidates; zero derives.
score_scaleFloat32The logit scale; zero derives it from the index's frozen geometry.
statsOptional[Pointer[DenseTraversalStats, stats_origin]]Receives this call's traversal telemetry; absent skips reporting.