Skip to main content

Prepare an operation by name

Use KernelRequest when an application or framework must select an operation without including its typed header. Link SimaKernels::request and include <simaai/kernels/request.h>. Runtime can expose these same types through its own public header; there is no second tensor representation.

#include <simaai/kernels/request.h>
#include <array>
namespace k = simaai::kernels;

// Inside the application's preparation function:
const std::array inputs{k::TensorSpec{{1, 224, 224, 3}, k::DType::Float32}};
const std::array outputs{k::TensorSpec{{1, 224, 224, 3}, k::DType::Int8}};
const std::array params{
k::Parameter{"multiplier", 0.25F},
k::Parameter{"zero_point", -3},
k::Parameter{"rounding", "nearest_even"}};
auto result = k::make_executable(
{"quant", k::Target::EV74, inputs, outputs, params});
// Check Result<Executable>, then give the executable to Runtime preparation.
// This call does not allocate device buffers or submit device work.

One preparation path, unchanged execution​

The generated resolver selects an operation-local request.cpp, which decodes its fields and calls its typed make_executable(). The typed factory and check_inference() remain authoritative for shapes, dtypes, layouts, numerical parameters and backend availability. No operation-name lookup, string parsing or parameter decoding occurs in submission, completion or numerical loops.

Tensor specifications are the canonical TensorSpec: explicit inputs and outputs, actual rank up to six, dtype separate from physical layout. Prepared executables retain everything they need; caller spans need only remain valid until make_executable() returns. Parameter names, strings, arrays and records own their storage. Device allocation, binding lifetime, scheduling and cache coherency remain Runtime responsibilities.

The build registers only its available operations: the host profile excludes BoxDecode; the EV74-only profile excludes A65-only operations. Unknown names return InvalidOperation; unsupported targets return UnsupportedTarget when the operation exists. There is no hidden backend fallback. This is a version-matched C++ API, not a serialized format or stable binary ABI.

Discover compiled implementations​

operations() returns immutable operation names and their compiled targets; find_operation(name) returns an entry or nullptr. Names and target spans have library lifetime. Enumeration order is not an operation identity.

Use this catalogue during graph preparation to select an explicit target. It is generated from the same registrations and linked providers as the resolver, not a second support matrix. A listed EV74 provider does not prove that the connected device has matching firmware. Discovery does not replace canonical admission or Runtime's device-capability checks.

Inspect a checked executable​

inspect_executable(executable) returns Result<ExecutableInspection>. Check the result, then retain the inspection while using its input/output specs, physical requirements, workspace, ownership flags or preparation facts. It retains the executable, so releasing the original handle does not invalidate these spans.

Inspection validates structural consistency; it does not repeat numerical inference, authorize actual buffers or provision resources. Moved-from inspections are empty and cannot authorize preparation. Numerical operations still obtain their contracts from canonical factories.

Two identity checks serve different purposes:

  • a == b means both handles retain the exact same immutable checked state. Independently prepared equivalent requests are different states.
  • same_contract_resources(a, b) compares retained target, tensor-contract and resource-recipe identities without allocation or deep comparison. It returns false for empty handles and is not permission to reuse another executor's resources.

Bind dynamic geometry once​

bind_variant(executable, capability) returns a retained operation-owned ExecutableVariant. Bind it during graph preparation, inspect its fields() and contract_policy(), then retain it. On a geometry-cache miss, call apply_variant(capability, request) with explicit specifications and positional values in that field order. Cache the resulting prepared operation in the execution service; ordinary hits reuse it without name lookup or parameter decoding.

Operation/capabilityPolicyOrdered fields
EV74 Preproc geometryFullRechecksource_roi, source_rois, destination, padding
A65 BoxDecode image_sizePreserveContractimage_size

Preproc requires new input/output specs and explicit destination/padding values. It retains static format, interpolation, color, normalization and quantization policy, checks the new geometry canonically, and regenerates accepted-ROI facts. An absent optional value clears that field; an empty ROI list remains an empty batch rather than an ordinary full-frame request.

BoxDecode accepts integer [width, height] and forbids port overrides. It validates geometry while retaining the exact checked contract, model tables, execution entry and resource recipe. Runtime separately decides whether its own prepared resources can be reused.

Unsupported capabilities and invalid values fail explicitly. Applying a variant never mutates the base or an in-flight executable. New geometry can allocate and require preparation; a cache miss may occur every frame when geometry changes continuously. This interface does not promise allocation-free cache misses or replace buffer-binding and lifetime checks.

Strict values​

  • Fields are case-sensitive. Unknown names and duplicate names are errors, including inside records. Enums use the exact strings below, not numeric IDs.
  • Integers preserve signedness until checked against the destination type. Floating values are never truncated into integers; booleans are not integers.
  • Float fields accept floating values, not strings or integers. Double-to-float rounding follows normal C++ conversion, but finite overflow and nonzero underflow-to-zero are rejected. NaN/Inf admission is operation-specific.
  • ParameterArray contains scalars and is checked for the required length and element types. ParameterRecords contains flat named scalar records only; recursive dictionaries and JSON are not part of this API.
  • Absent optional values keep the typed operation defaults. Supplying an invalid value never falls back to a default. Error field/message pointers refer to static strings and remain valid after request destruction. Unknown/duplicate fields report parameters, rather than retaining an unsafe caller string.

Parameter names​

The operation pages and typed headers define numerical semantics and port roles. This table defines only their named spelling. Unless marked required, fields retain typed defaults. All floating fields below require floating C++ values.

OperationNamed fields
cast, casttess, detesscast, detess, histogramNone; tensor specifications select conversion/storage.
quant, quanttessRequired float multiplier; integer zero_point (default 0); rounding (default nearest_even): nearest_even, toward_zero, toward_positive, toward_negative.
dequant, detessdequantRequired float scale; integer zero_point (default 0).
tessOptional integer int8_channel_padding; typed admission decides when required/forbidden.
argmaxInteger axis (default -1); bool keepdims (default false).
fast, fast_briefInteger threshold (default 30); output_encoding: separate (default) or packed; optional unsigned-range integers grid_columns, grid_rows, minimum_distance (see below).
trackerUnsigned-range integers window_half (default 7), max_iterations (20), pyramid_levels (0).

FAST grid selection​

Omit all grid fields to keep raster-first selection. Supplying any grid field enables grid selection, including an explicit minimum_distance = 0. Omitted grid fields default to one column, one row and zero minimum distance. grid_columns must be in 1..W, grid_rows in 1..H, and minimum_distance in 0..65535 pixels. The grid covers the full input image.

The FAST contract defines cell quotas, score ordering, ties and greedy spacing. FAST+BRIEF uses the same selection before computing descriptors for the retained points.

Preproc​

FieldValue
input_formatgray, rgb (default), bgr, nv12, i420, nv16
output_formatgray, rgb (default), bgr
interpolationidentity, nearest, bilinear (default), bicubic, box_average
color_matrixbt601_full (default), bt709_full
source_roiOptional integer [x, y, width, height]; absent means full source frame
destinationRequired integer [x, y, width, height] within output canvas
source_roisFlat record list; each record requires integer source_index, x, y, width, height
affine_offset, affine_multiplierThree float values; defaults [0,0,0] and [1,1,1], respectively
paddingThree integers in [0, 255], semantic RGB raw pixels; default [0,0,0]
quantization_multiplierOptional float; enables typed quantization
quantization_zero_pointInteger, default 0; requires quantization_multiplier

source_rois absence selects ordinary preprocessing; an explicit empty list selects an empty ROI batch. The typed contract owns conflict checks, invalid-ROI filtering and output-capacity limits; the decoder only validates record fields. Each record may also provide destination_x, destination_y, destination_width and destination_height, all together. Omit all four to inherit the common destination. Rectangles are checked against the output canvas; the caller, not the kernel, chooses any aspect-ratio policy.

Per-plane pitch remains in TensorSpec.layout, not a parameter or a buffer address. Plane offsets are Runtime bindings. Dynamic image geometry is a new checked request/variant, not mutation of an in-flight executable.

BoxDecode​

Required fields are profile, heads, model_input_size, original_image_size, num_classes, max_detections and detection_threshold. Sizes are integer [width, height] arrays. The two limits are class count and final output limit, not implicit output allocation.

  • profile: yolo26_v1, yolov5_v1, yolov7_v1, yolo_dfl_v1, yolov6_v1, yolox_v1, decoded_v1, efficientdet_v1, detr_v1, centernet_v1, rcnn_proposals_v1, ssd_v1.
  • heads: record list with required integer boxes_input, scores_input, and optional integer extra_input, auxiliary_input.
  • Optional quantization: record list with required integer input, required float dequant_scale, and optional integer zero_point. Duplicate input records fail; absence remains distinct from scale one.
  • Required float detection_threshold; optional float nms_iou_threshold (default 0).
  • score_activation: identity, sigmoid, softmax. Omission retains the typed recipe's default resolution/required-field checks.
  • task: detection (default), pose, segmentation.
  • resize: centered_letterbox (default), stretch (required for SSD/DETR).
  • ssd_recipe: none (default), ssd300, mobilenet300, mobilenet320, torchvision_lite320.
  • Integer mask_basis_input, keypoints, decoded_anchors_per_cell; bool decoded_objectness, decoded_split_extents. Their defaults are absent, 17, 1, false and false, respectively.

For example, an explicit two-port head is represented as:

k::Parameter heads{"heads", k::ParameterRecords{
{{"boxes_input", 0U}, {"scores_input", 1U}}}};

SuperPoint​

Required integer-array model_input_size is [width, height]; integer topk_capacity is required. Optional profile is a65_v1, lightglue_v1 or magicleap_demo_v1 (default a65_v1). Other optional fields are float detection_threshold (default 0), integer nms_radius, and integer border_margin (both default -1, resolved by the selected profile).

Each of detector_quantization_scale and descriptor_quantization_scale enables that port's optional quantization. Its accompanying _zero_point is an integer (default 0) and _reciprocal is a bool (default false); either requires its corresponding scale. Scales retain double precision, as in the typed contract.

Add an operation​

Keep request.cpp beside the operation's semantic header. Use the private common/request/reader.h for strict field decoding, call the typed factory, and register with sima_register_operation(). CMake generates resolver membership from these registrations: no central enum, static-initializer registry, Runtime switch or plugin file is needed for ordinary math.

tests/request_contract.cpp compares named and typed preparation, verifies EV packet equality, exercises rejection cases and checks retained host execution. The installed-package consumer separately compiles the generic header and links the preparation APIs using only SimaKernels::request. The package exports SimaKernels_REQUEST_CATALOGUE_API_REVISION as 1 for this preparation contract; it is not the release version or a stable binary ABI. A matching declaration or revision value alone is not proof that the implementations link. These are contract checks, not EV device numerical or latency qualification.

Kernel-owned preparation facts​

preparation_facts(executable) returns a read-only span<const Parameter>. The executable owns these values; retain it while using the span. These are cold, immutable results of canonical validation, not per-inference output data. Runtime exposes the same accessor for a PreparedOperation. Other operations, ordinary single-ROI Preproc and empty executable handles currently return no facts.

Preproc ROI-batch preparation publishes:

FactValueMeaning
requested_roisunsigned integerAll supplied records, including later drops.
valid_roisunsigned integerAccepted output slots, after capacity filtering.
dropped_invalidunsigned integerInvalid source index or nonpositive extent.
dropped_overflowunsigned integerValid records beyond output capacity.
source_indicessigned integer arraySource frame index for each accepted output slot, in order.
accepted_roisscalar recordsAccepted source index, source rectangle and resolved destination rectangle for each output slot.

An explicitly empty source_rois list publishes zero counts and an empty index array. Consumers use these checked facts rather than repeating ROI filtering. No fact lookup occurs in kernel submission, completion or numerical loops.