C · Fingerprints

Fingerprints

#include <stringzilla/capabilities.h>#include <stringzilla/overlap.h> 6.0.0-rc.1 · 91a27bdd

A window is a fixed-width byte n-gram, and the overlap of two texts at that width is the count of one's windows that occur in the other, over whichever of the two has more. Every query is hashed once into one B-tree over every width's window hashes, and every candidate then streams through the forest, hashing its own windows and probing. Nothing is stored per candidate, so the candidates may change round to round while the queries and the widths stay.

Window hashes come from a prefix difference, H(i, w) = P(i + w) − P(i) × bʷ mod p, which costs one modular multiply-add at any width and any offset; widths need not form a doubling chain. The modulus is a 32-bit prime chosen for collision weight, so a window hash is full-width.

Public API

Every register-level step behind these - the prefix chain, the window hashing, the key sort and the B-tree probe - is public per backend in overlap/serial.h and its SIMD backends, named by positions per step, such as sz_overlap_f64x4_prefix_hash_step_haswell, so a caller driving its own loops binds those steps and skips these verbs entirely. The tree layout is the same on every backend, so any of them may probe it.

API

Types

sz_kernel_overlap_engine_init_tSignature of every sz_overlap_engine_init kernel.
capabilities.h:886 ↗
typedef sz_status_t(*) sz_kernel_overlap_engine_init_t(struct sz_overlap_engine_t *, sz_strings_view_t const *, sz_size_t const *, sz_size_t, sz_size_t, sz_allocator_t *, sz_stream_t);
sz_kernel_overlap_scores_tSignature of every sz_overlap_scores kernel.
capabilities.h:891 ↗
typedef sz_status_t(*) sz_kernel_overlap_scores_t(struct sz_overlap_engine_t *, sz_strings_view_t const *, sz_f32_t, sz_u32_t *, sz_size_t, sz_size_t, sz_stream_t);

Functions

sz_overlap_engine_initPrepares queries into one block from allocator, for the best capability of capabilities that has an init kernel.
overlap.h:76 ↗
sz_status_t sz_overlap_engine_init(
    sz_overlap_engine_t *engine,
    sz_strings_view_t const *queries,
    sz_size_t const *window_widths,
    sz_size_t window_widths_count,
    sz_size_t candidates_budget,
    sz_capability_t capabilities,
    sz_allocator_t *allocator,
    sz_stream_t stream);

Backends

  • sz_overlap_engine_initserialhaswellskylakeneoncudablackwellrocmmetal

Every width's window hashes of one query share that query's B-tree, so its sort runs once per batch rather than once per round, and the probe depth grows only logarithmically as widths are added to the batch.

Parameters

engineoutLeft untouched unless the call succeeds.
queriesinThe texts whose windows are sorted into the forest; read on the host.
window_widthsinWindow widths in bytes; a width past a text scores zero for its pairs.
window_widths_countinNumber of widths, which is the last axis of every output.
candidates_budgetinCandidates one round may carry, for a backend whose rounds keep state per candidate, zero asking for its default; one that keeps none ignores it.
capabilitiesinOne device's capabilities, like sz_capabilities_enabled_cpu or sz_capabilities_enabled_metal report; its group picks the CPU or a GPU vendor.
allocatorinSource of the forest's block, or STRINGZILLA_NULL for sz_allocator_init_unified_best of capabilities; stored by value, so sz_overlap_engine_free needs no allocator of its own.
streaminNull on the CPU. On a GPU, the stream to queue on, also naming the device: a cudaStream_t, a hipStream_t, or an id<MTLCommandQueue>; null for the default.

Notes

May join stream; no scoring verb ever does.

Statuses

sz_overlap_engine_freeReturns both of engine 's blocks to the allocator that built them, once the work queued on stream is done with them, and leaves it empty.
overlap.h:83 ↗
void sz_overlap_engine_free(
    sz_overlap_engine_t *engine,
    sz_stream_t stream);
sz_overlap_scoresWindow overlap of every prepared query with every candidate, at every width of the batch, by the kernel of the capability engine was prepared for, exact within radius.
overlap.h:130 ↗
sz_status_t sz_overlap_scores(
    sz_overlap_engine_t *engine,
    sz_strings_view_t const *candidates,
    sz_f32_t radius,
    sz_u32_t *matches,
    sz_size_t matches_query_stride,
    sz_size_t matches_candidate_stride,
    sz_stream_t stream);

Backends

  • sz_overlap_scoresserialhaswellskylakeneoncudablackwellrocmmetal

A batch of queries prepared once scores any number of candidate batches, and a host round block only grows, so a batch within the longest seen allocates nothing. A width's count is the candidate's windows the query also holds. A pair's misses are the longer side's windows the other leaves unmatched, summed over every width, and its distance is those misses over the longer side's windows in all. A pair within radius is counted exactly; a pair past it counts zero at every width, on every backend, or exactly when within rounding of the share, less than 2⁻²⁴ past it. A pair is dropped once its misses provably pass that share of its longer side, often from the two lengths alone, before a byte is read.

The count of query q, candidate c and width w sits at:

*  matches[q * matches_query_stride + c * matches_candidate_stride + w]
*  

Parameters

engineinThe prepared forest; a host round block grows here and is never shrunk. A device engine keeps no stream, so on CUDA any number of streams may score it at once; on Metal its one round block orders the rounds on the device's one queue.
candidatesinThe texts whose windows are probed against the forest's, on the residency the engine was built for: any layout on the CPU, and on a device a tape sz_strings_to_tape_best wrote into a unified allocator.
radiusinThe share of its longer side's windows a pair may miss, in [0, 1]; 1 or more keeps every count exact.
matchesoutCounts with a unit-strided width axis, laid out as shown below.
matches_query_strideinEntries from one query's plane to the next, at least the candidates times matches_candidate_stride.
matches_candidate_strideinEntries between candidate rows, at least the widths the engine was prepared at.
streaminNull on the CPU. On a GPU, the stream to queue on, which also names the device the round runs on; null for the default.

Notes

  • Asymmetric: a candidate's window occurrences count against a query's distinct windows, so swapping sides changes the count when either repeats a window.
  • Never joins, so the caller joins stream before reading matches.

Statuses

sz_overlap_engine_init_serialPrepares queries into one block from allocator, for the serial kernels.
overlap.h:150 ↗
sz_status_t sz_overlap_engine_init_serial(
    sz_overlap_engine_t *engine,
    sz_strings_view_t const *queries,
    sz_size_t const *window_widths,
    sz_size_t window_widths_count,
    sz_size_t candidates_budget,
    sz_allocator_t *allocator,
    sz_stream_t stream);

Backends

  • sz_overlap_engine_initserialhaswellskylakeneoncudablackwellrocmmetal

Parameters

engineoutLeft untouched unless the call succeeds.
queriesinThe texts whose windows are sorted into the forest; read on the host.
window_widthsinWindow widths in bytes; a width past a text scores zero for its pairs.
window_widths_countinNumber of widths, which is the last axis of every output.
candidates_budgetinCandidates one round may carry; the serial rounds keep no state per candidate and ignore it.
allocatorinSource of the forest's block, or STRINGZILLA_NULL for sz_allocator_init_unified_serial; stored by value, so sz_overlap_engine_free needs no allocator of its own.
streaminNull on the CPU.

Statuses

sz_overlap_scores_serialWindow overlap of every prepared query with every candidate, at every width of the batch, by the kernel of the capability engine was prepared for, exact within radius.
overlap.h:155 ↗
sz_status_t sz_overlap_scores_serial(
    sz_overlap_engine_t *engine,
    sz_strings_view_t const *candidates,
    sz_f32_t radius,
    sz_u32_t *matches,
    sz_size_t matches_query_stride,
    sz_size_t matches_candidate_stride,
    sz_stream_t stream);

Backends

  • sz_overlap_scoresserialhaswellskylakeneoncudablackwellrocmmetal

A batch of queries prepared once scores any number of candidate batches, and a host round block only grows, so a batch within the longest seen allocates nothing. A width's count is the candidate's windows the query also holds. A pair's misses are the longer side's windows the other leaves unmatched, summed over every width, and its distance is those misses over the longer side's windows in all. A pair within radius is counted exactly; a pair past it counts zero at every width, on every backend, or exactly when within rounding of the share, less than 2⁻²⁴ past it. A pair is dropped once its misses provably pass that share of its longer side, often from the two lengths alone, before a byte is read.

The count of query q, candidate c and width w sits at:

*  matches[q * matches_query_stride + c * matches_candidate_stride + w]
*  

Parameters

engineinThe prepared forest; a host round block grows here and is never shrunk. A device engine keeps no stream, so on CUDA any number of streams may score it at once; on Metal its one round block orders the rounds on the device's one queue.
candidatesinThe texts whose windows are probed against the forest's, on the residency the engine was built for: any layout on the CPU, and on a device a tape sz_strings_to_tape_best wrote into a unified allocator.
radiusinThe share of its longer side's windows a pair may miss, in [0, 1]; 1 or more keeps every count exact.
matchesoutCounts with a unit-strided width axis, laid out as shown below.
matches_query_strideinEntries from one query's plane to the next, at least the candidates times matches_candidate_stride.
matches_candidate_strideinEntries between candidate rows, at least the widths the engine was prepared at.
streaminNull on the CPU. On a GPU, the stream to queue on, which also names the device the round runs on; null for the default.

Notes

  • Asymmetric: a candidate's window occurrences count against a query's distinct windows, so swapping sides changes the count when either repeats a window.
  • Never joins, so the caller joins stream before reading matches.

Statuses

sz_overlap_find_kernelFinds the overlap kernel of kind, from the best of capabilities.
overlap.h:260 ↗
sz_status_t sz_overlap_find_kernel(
    sz_kernel_kind_t kind,
    sz_capability_t capabilities,
    sz_kernel_punned_t *kernel,
    sz_capability_t *capability);

Parameters

kindinThe verb whose kernel to find.
capabilitiesinThe mask to pick the best capability from.
kerneloutThe kernel, or null when none of capabilities has it.
capabilityoutThe capability the kernel belongs to, or zero.

Statuses