Compute Fit — methodology

Method version 1.9.0 · engine: /engines/compute-fit/ · reads the normalised benchmark database, the power-mode registry, the JetPack configuration registry and the hardware catalog, with its vendor-sourced precision and runtime support lists. No dataset of its own.

A capacity check, not a recommendation. One platform in, one answer out — and every number carries the row it came from, the class of that row, and whether it was measured or modelled.

Input rules

Inputs (WP-01). A field that is not stated takes its documented default and is listed in provenance.defaulted; a field that is stated but invalid — a count of 0, a negative, a fraction or a non-number, true in place of a count, an unknown value of an enumerated input, or an empty string — is rejected with VALIDATION_ERROR naming the field, never replaced by a default.

Input keys (WP-02). The engine accepts one list of input keys — the inputs documented here and their declared backward-compatible aliases. Unknown input keys are rejected with VALIDATION_ERROR naming the key: an invented or misspelt key is never silently ignored, a __ test hook never reaches the engine, and an alias sent together with the key it stands for is rejected too (the engine would read only one of them). export_json.inputs echoes every input the engine honoured, so replaying it reproduces the result.

Contents

  1. What it decides, and what it does not
  2. The required load
  3. The throughput resolver
  4. Evidence class and demotion
  5. The three latency tiers
  6. What the database actually contains
  7. The headroom target
  8. Power modes
  9. Precision, runtime and batch
  10. The verdict ladder
  11. The model ladder
  12. What invalidates a result
  13. Method changelog

1. What it decides, and what it does not

Compute Fit answers one question: on this platform, in this configuration, does the compute hold this load — and where does every number come from. It returns the required frames per second, the throughput the benchmark database resolves, the rows behind that figure with their sources, a latency reported by tier, and a ladder of what else would run on the same silicon.

It does not recommend a platform. The engines it replaces did: the legacy compute sizer answered a throughput question with a theoretical TOPS figure and then named a device, making it a third platform picker beside two others that already existed. Compute Fit takes one platform and answers for it, so its answer is checkable against that platform's own benchmark rows. When the question is which platform, that is Hardware Match.

It also does not model the rest of the pipeline. Every benchmark row in this database is inference-only: decode, preprocessing, tracking, encoding and the network are not in these numbers. Camera Stream Capacity models those stages, and an end-to-end latency budget is a separate question this engine deliberately does not answer.

2. The required load

Either a direct target throughput, or a camera load resolved by the sizing expression Frigate publishes for its own detectors: cameras × detect fps × the share of frames with motion. The default motion share is 1.0 — the worst case, every camera detecting at once — because a capacity plan that assumes quiet cameras fails on the day something happens in front of all of them.

The detect rate is not the camera's frame rate. A camera streaming at 30 fps whose detector runs at 5 fps needs five inferences per second from this engine and thirty decodes per second from another. Compute Fit sizes the first; the decode side belongs to Camera Stream Capacity.

3. The throughput resolver

There is one resolver and no second path. The Benchmark Explorer's expected range is asked for the hardware, model family, variant, precision and runtime; it reads the normalised database first and falls through to the estimator's benchmark hierarchy when a precision has no row, reporting the tier chain it tried. Nothing in Compute Fit reaches around it to a different table.

When rows exist, they are narrowed to the batch size asked for if any row was measured there — a batch-8 figure and a batch-1 figure are different measurements on the same silicon and mixing them into one range is meaningless. The lowest figure in the resulting set is the reported capacity, not the median and not the best row anyone published. Published benchmarks vary by batch, thermal state, software version and harness; the pessimistic edge is the number most likely to survive a real deployment. The full range is printed beside it so the disagreement is visible rather than hidden.

That reference figure is then multiplied once by the shared multi-stream efficiency curve at the stream count (src/v2/multi_stream_efficiency.js, class E) and by a power-mode calibration where one exists. Both factors are printed, so available = reference × efficiency × power factor can be recomputed from the numbers the result returns. Per-count headroom, max_cameras_at_detect_fps and the throughput constraint all read the same capacityLadder; there is no separate primary_bottleneck. A capacity figure whose arithmetic cannot be checked from what it publishes is not falsifiable.

4. Evidence class and demotion

The class is inherited from the rows: C when a named publisher measured and published the figure, D when it is EdgeAIStack-derived with the derivation stated. Classes A, B and E do not occur for a throughput in this corpus, and the engine never claims one.

A class C figure is demoted to D in two cases: when the rows were measured at a different input resolution than the one asked for, so the figure has been scaled by the pixel ratio (§8a); and when a power-mode factor has been applied, because that factor is itself a class D calibration. Both demotions are stated in words on the check, with the ratio or factor printed, and neither is silent. When no input resolution is given, the rows are used at the size they were measured at and nothing is scaled or claimed.

Class is provenance. Whether a miss through the figure can be a FAIL is its elimination authority, from the steps between the rows and the figure. The pixel-ratio scaling (never upward) and the pessimistic edge of several measured rows are bounded steps: a miss through them is a FAIL and the verdict NO FIT. A power-mode factor, the multi-stream efficiency curve, a cross-platform, cross-task or GFLOPs scaling, a TOPS estimate and a class D corpus row are estimates: a miss through any of them is REQUIRES VALIDATION with the modelled shortfall stated, and the verdict NEEDS VALIDATION. One bound applies to the power-mode factor: a lower power mode never runs the same row faster (bug #209), so when the factor is below 1 and it is the only estimate in the chain, the check is also made against the row at its own, higher mode, and a miss there FAILs on the class of the row that set the figure. The derived-reciprocal latency takes the throughput's authority and the same ceiling.

5. The three latency tiers

This is the part the engine exists for. Of the benchmark rows that report a latency, all but sixteen report a number within two per cent of 1000 divided by the frame rate on the same row: the latency was computed from the throughput, not observed. The engine that Compute Fit replaces published that reciprocal as a latency, with no class, no source and no chain — at every tier, including the one where the throughput itself was a theoretical ceiling.

The fix starts at the data. Every row in the benchmark database is now stamped, at the point the database is built, with latency_source: measured when the figure was observed, derived_reciprocal when it equals 1000/fps to within two per cent. The p99 column carries latency_p99_source, and every p99 in the database is derived — a modelled 1.20–1.43× multiplier over the p50, never an observed tail. Compute Fit and its validation rules read that flag; neither re-derives the test at request time, and no page can present a reciprocal as a measurement.

TierWhat it isClassStatuses it can return
measuredA latency a named publisher observed and published, flagged latency_source: measured on a class C row and cited with that publisher's pageCPASS, NEAR LIMIT, FAIL — the normal ladder
statedAn independent figure — not the reciprocal of its own row's throughput — whose only source is the EdgeAIStack benchmark corpus. Some of those rows say in their own derivation that they were estimated from a TOPS budgetDFAIL when it already exceeds the target, otherwise REQUIRES VALIDATION. Never PASS
derived_reciprocal1000 divided by the resolved throughput. It assumes one frame in flight with no queueing, preprocessing or copyDFAIL when the bound already exceeds the target, otherwise REQUIRES VALIDATION. Never PASS
unknownNeither a row nor a throughput resolved—UNKNOWN

The asymmetry in the two class D tiers is the point. A reciprocal is a lower bound on real latency: the real figure can only be worse. So a bound that already exceeds your target proves a genuine miss, while a bound under your target proves nothing at all — hence FAIL in the first case and REQUIRES VALIDATION, never PASS, in the second. The same rule is applied to the corpus-derived stated tier: a class D number cannot certify a target, only fail one.

Without a latency target no latency check runs at all, and the result reports a floor_ms explicitly labelled as the derived reciprocal. There is one further figure the engine carries but never uses as evidence: an internal Hailo p50/p99 table that exists in the code with no source record anywhere in the repository. It is reported as context, class D, with that caveat printed — it is not laundered into the check.

6. What the database actually contains

The honest limits, stated rather than filled. The database holds 567 rows over 21 hardware ids and 49 model families, of which 163 are class C and 404 class D. Only 166 of the 1,029 possible platform × family combinations carry a row at all, so a query outside that coverage lands on the estimator's fallback rather than on a measurement.

  • Latency is thin everywhere. 539 of the 555 rows that report a latency computed it as 1000/fps. Sixteen were observed independently, and only three of those are class C rows with an external publisher behind them.
  • Batch is thinner. 553 of 567 rows are batch 1. The only rows above it are fourteen Hailo rows at batch 8. Anything else is UNKNOWN, never extrapolated.
  • Resolution is concentrated. 428 of 567 rows were measured at 640×640, so any other input size asked for is a figure scaled by the pixel ratio and reported class D — or UNKNOWN for a model whose cost does not follow the pixel count.
  • Power-mode joins are weak. Only a minority of Jetson rows resolve to a real nvpmodel preset, and the throughput calibration covers four platforms. A benchmark row is never joined to a preset the vendor does not ship.
  • One catalog platform has no rows at all, and four hardware ids in the database are reference platforms outside the catalog. Both facts are reported rather than papered over.

None of this is filled by inventing numbers. It is filled by measurement: the submission protocol already accepts a latency figure, and a measured row on a real target replaces a modelled one the moment it lands.

7. The headroom target

The default is 20 %, and it is class E — engineering judgement, not measurement. It is chosen so the resulting utilization target, 0.80, is exactly the shared NEAR LIMIT threshold every other V2 engine already uses, rather than a second private threshold living in this engine alone.

It does one thing: it moves the NEAR LIMIT line on the throughput check. There is deliberately no separate headroom constraint, because on the default it would say exactly what the throughput check's own NEAR LIMIT status already says, and two thresholds that mean the same thing are how a stack ends up with four of them. Raise the target and a configuration that was a clean pass becomes NEAR LIMIT at the same utilization; nothing else in the result moves.

8. Power modes

The power-mode registry knows watts and clock ceilings but no throughput. The only mode-to-throughput relation in the repository is a calibration table covering four platforms, documented as part-measured and part-estimated (class D).

A requested power mode is a ceiling. The highest supported preset at or below it is selected, and the result publishes the request, the ceiling in watts, the selected preset and the substitution note (workload.power_mode_request). When every preset of the module draws more than the ceiling, a power_mode_ceiling check FAILs (lowest preset watts against the ceiling) and the verdict is NO FIT — the engine never runs a higher preset and warns. A value that names no preset, no wattage and not MAXN is a validation error naming power_mode. With no power mode given, the module's registry default preset is used — the same mode Camera Stream Capacity prints and Hardware Match plans at — so one load gives one throughput in every engine.

The factor is relative to the row's own mode. A benchmark row was measured at some mode; the figure at the selected preset is row fps × f(selected) / f(row mode), where a row that states no mode is taken at the table's reference mode. A 15 W row read at 25 W is therefore scaled up, never down, and more allowed power never lowers the modelled throughput of the same row. On a platform with no calibration the row is used as measured and the result says so.

8a. Input resolution

When no row was measured at the input resolution asked for, a detection, segmentation or pose network's figure for a larger input is scaled down by the pixel ratio: fps × pixels_row ÷ pixels_requested, a first-order convolutional cost model (class D). A smaller input is not scaled up: it is not credited with more throughput than was measured, because fixed per-frame costs do not shrink with the pixel count, so the measured figure is used (class D). The step publishes the true pixel_ratio and the applied_ratio (the fps multiplier actually used, never above 1), and the assumption says which of the two happened. Transformer models and classifiers are not scaled — their cost does not follow the pixel count — so for them a size with no row is UNKNOWN with the reason.

9. Precision, runtime and batch

The precision check reads the platform's supported-precision list and the runtime check its supported-runtime list. Both lists are sourced per platform from the vendors' own documentation — NVIDIA's TensorRT support matrix, compute-capability table, Jetson data sheets and release notes; Google's Edge TPU documentation; Hailo's data sheets and HailoRT documentation; Rockchip's RKNN-Toolkit2 and RKLLM documentation; Intel's OpenVINO documentation; and each runtime's own platform pages. A precision or runtime the vendor documents, as supported or as not supported, is class A, and the check cites the document (detail.evidence_kind: vendor_documentation); a value no vendor document settles either way stays a class E catalog assertion, with no source, and the check says so (catalog_assertion). When benchmark rows at exactly this precision and runtime resolve the throughput, the precision check reads its class from those rows instead, as before.

A listed INT4 means the platform runs 4-bit weight quantization (W4A16 or A8W4 — the meaning the benchmark database already gives INT4); a precision the hardware reaches only in emulation is not listed. The lists are per platform: they do not say which model families run at a precision, so a vision model asked for at a precision with no benchmark row resolves to a modelled figure, never a measured one. The runtime check reads the list on non-Jetson platforms; on Jetson it is replaced by the Jetson Configuration Checker's sourced verdict, which cites NVIDIA's own release notes for the JetPack-to-runtime pairing.

The precision default (method 1.5.0). A named precision is evaluated as named. With none named, the precision is the planning default of the task the model registry files the named model under — FP16 for a YOLO11-seg or YOLO11-pose model, INT8 for every other model — listed in provenance.defaulted and in derived_inputs as DERIVED. This engine takes no task: the model is the workload. A default the platform cannot run is not a runnable default: on an INT8-only accelerator (Coral, Hailo) the FP16 task default falls back to INT8, the platform’s supported precision, recorded as DERIVED with the reason (“FP16 task default not supported on Hailo-8; INT8 is the platform’s supported precision”). A named FP16 there is evaluated as asked: UNSUPPORTED, NO FIT.

A precision or runtime the platform cannot run resolves no throughput at all. Established on sourced evidence — a vendor-documented support list (class A), or the Jetson Configuration Checker's runtime verdict, which cites NVIDIA's release notes — it is UNSUPPORTED and makes the verdict NO FIT. A value no vendor document settles is a class E assertion, and class E never independently eliminates: a configuration excluded only on class E evidence is REQUIRES VALIDATION with the demoted status stated, the verdict NEEDS VALIDATION, and still no throughput is resolved. The estimator hierarchy will happily scale a figure for FP16 on an INT8-only accelerator; a number about a configuration that cannot exist is a number about nothing, so the support checks gate the resolver rather than sitting beside it.

The batch check asks one thing: is there a row at this batch size. Batch 1 passes and says how many rows back it. A batch above 1 with a matching row passes and cites it. A batch above 1 without one is UNKNOWN — never a scaled batch-1 figure with a made-up factor.

When the rows behind the throughput match the precision and runtime asked for, the precision check carries their class as benchmark metadata, and the batch check carries the class of the rows at the batch asked for. Neither measures anything: each restates that a row exists. So each names the check that already carries those rows in evidence_ref — the throughput check, or the precision check when the rows gave no frame rate — and a consumer that averages evidence classes over checks counts those rows once. The reference changes nothing either check says: status, class and confidence are still the rows'.

10. The verdict ladder

The same ladder every V2 engine uses, applied to the checks above, in this order: any FAIL or UNSUPPORTED is NO FIT; any UNKNOWN, REQUIRES VALIDATION or VERSION RISK is NEEDS VALIDATION; any NEAR LIMIT is FIT WITH RISKS; otherwise FIT. A FAIL or UNSUPPORTED is only raised on authoritative or bounded evidence (§4); a miss on planning-only evidence reads REQUIRES VALIDATION.

UNKNOWN never fails a configuration and never passes it free. It caps the verdict at NEEDS VALIDATION until somebody measures the thing that is unknown. In practice that means most results carrying a latency target land on NEEDS VALIDATION, because most latencies in the corpus are derived — which is an accurate description of the evidence, not a defect in the engine.

11. The model ladder

Instead of naming a different platform, the result shows up to five closest-margin models that still fit on this silicon at the same efficiency and power factor. Model selection is Model Match's job; the handoff link opens that engine with the same workload. The combination you asked for may appear in that short list when it fits with small margin.

12. What invalidates a result

  • A latency that matters. If the deployment has a real latency requirement, treat every non-measured tier as a hypothesis and measure on the target — the reciprocal is a lower bound and the real figure includes queueing, preprocessing, copies and the rest of the pipeline that no row here contains.
  • Software versions. A benchmark measured on one JetPack, TensorRT or SDK release is not portable to another; the rows carry their dates and, where the publisher stated one, their software version.
  • Thermal state. Published benchmarks are usually short runs on a cool device. Sustained throughput on a passively cooled node in a warm enclosure can be materially lower — that is the Thermal Feasibility Checker's question.
  • A modelled fallback. When no row matched, the figure came from a precision ratio, a cross-platform scaling or a theoretical ceiling. It is class D and it is a starting point for a measurement, not a capacity figure. A throughput modelled from a theoretical TOPS ceiling, or scaled onto a platform that has no benchmark row of its own, never reaches PASS and never FAILs: a modelled miss cannot rule a configuration out, so the throughput check reads REQUIRES VALIDATION whether the load fits or not, and the verdict is at best NEEDS VALIDATION.
  • Input resolution. Three-quarters of the corpus is 640×640; a figure scaled down to a larger input by the pixel ratio assumes throughput is proportional to pixel count for that model on that silicon. A smaller input is given the measured figure, which is conservative: its real throughput may be higher.
  • The multi-stream efficiency curve and the headroom target are both engineering judgement, and a workload whose concurrency pattern differs from the modelled one will differ from this answer.
  • Everything outside inference. Decode, preprocessing, tracking, encoding, storage and network are not in these numbers at all.

13. Method changelog

MethodDateChange
1.9.02026-09-29Materiality, made honest (bugs #266, #267). The capacity_sweep row — published only when the multi-stream efficiency curve is not monotone for the platform, naming the maximum camera count over a full sweep — answers a different question than the one asked (does the requested load fit) and no longer decides the verdict: it stays published, the maximum still reads "not determined", but it cannot demote an otherwise-established FIT. The precision, batch and (off-Jetson catalog) runtime checks now declare their rollup significance explicitly (MATERIAL) rather than relying on their SELF/COMPATIBILITY comparison basis to default one way or another: the requested precision, batch and runtime are real facts the caller asked about, and an UNSUPPORTED or UNKNOWN result there still caps the verdict, now that the kernel honours a row explicitly marked INFORMATIONAL when deciding the core verdict. No verdict changes on any real catalog combination — the sweep only ever fires on an injected test seam (GAP-12 proves it monotone for every real platform today) — but every constraint row now also publishes required_for_verdict.
1.8.02026-09-29A stated runtime is judged as stated (bug #276), the same rule already applied to a named precision: a requested runtime with no benchmark row was silently resolved to the platform's native runtime on Hailo-8 / 8L / 10H and the runtime check then judged the substitute, so a Hailo-8 + TensorRT request read FIT with runtime_resolution naming the swap. TensorRT is vendor-documented as NVIDIA-only hardware (class A), the same standing as HailoRT's own device list, so a caller who states TensorRT on Hailo now gets the runtime check's own answer for TensorRT: UNSUPPORTED, class A, authoritative, and NO FIT — exactly like Coral + TensorRT. runtime_resolution is only ever populated when the caller did not name a runtime; a named runtime never triggers it, supported or not. Nothing changes when the runtime is omitted (still the platform's native runtime, marked defaulted) or when the stated runtime is the native one.
1.7.02026-09-29elimination authority (#263, owner ruling 2026-09-29). The throughput's derivation decides whether a miss can FAIL: pixel scaling and the pooled minimum are bounded; the multi-stream curve, a power-mode factor, a cross-platform, cross-task, GFLOPs or TOPS scaling and a corpus row are estimates, so a miss through them is REQUIRES VALIDATION with the shortfall stated (NEEDS VALIDATION, was NO FIT). A power-mode factor below 1 is bounded by the row at its own mode, on that row's class. The derived-reciprocal latency takes the throughput's authority and ceiling. The class E precision list (and the runtime list off Jetson) no longer eliminates: a configuration missing from it is REQUIRES VALIDATION and no throughput is resolved. Every row publishes elimination_authority.
1.6.02026-09-29The precision and runtime support lists are sourced (bug #275). Every catalog platform's supported-precision and supported-runtime list now cites the vendor's own documentation for each value: a value the vendor documents — supported, or not supported — is class A on the precision / runtime check, with the source cited and detail.evidence_kind: vendor_documentation; a value nothing settles stays the class E catalog_assertion, unsourced. Corrections the sources made: Jetson Thor T5000 / T4000 add FP8, BF16 and INT4 (Thor + FP8 was NO FIT on an UNSUPPORTED precision although 21 FP8 TensorRT rows exist; it now resolves them), the Jetson Orin modules and Hailo-8 / 8L / 10H add INT4 (4-bit weights), L4 / L40S add BF16 and FP8, A2 / A10 add BF16, and RK3588 / RK3588S drop INT4 (Rockchip's toolkits deploy no 4-bit weights on them). Those requests move between NO FIT and NEEDS VALIDATION accordingly; no other status, figure or verdict changes.
1.5.02026-09-29Segmentation and pose default to FP16 (owner ruling of 2026-09-29): with no precision named, a YOLO11-seg or YOLO11-pose model (the model registry’s task) is evaluated at FP16 — the precision of every measured YOLO11-seg / -pose row on Jetson Orin — and every other model at INT8, as before; on an INT8-only accelerator (Coral, Hailo) the FP16 default falls back to INT8, the platform’s supported precision (lead decision the same day). The default is listed in provenance.defaulted, in derived_inputs (DERIVED, with the reason for a fallback) and in an assumption, and marked workload.precision_default. A named precision is evaluated as named.
1.4.42026-09-29The precision and batch checks name the check that already carries the benchmark rows their class was read from, in detail.evidence_ref (the throughput check, or the precision check when the rows gave no frame rate), so a consumer that averages evidence classes over checks counts one row once — Model Match's evidence term counted the row behind a throughput three times (bug #264). No status, class, confidence, figure or verdict changes.
1.4.32026-09-28An absent power_mode is listed in provenance.defaulted (bug #248). With no mode named the answer was already sized at the module's registry default preset and said so (workload.power_mode_request and the assumption line), but the default was not recorded with the other defaults. A named mode — a preset, a wattage ceiling, maxn or default — is never listed, and neither is a module without presets. No figure changes.
1.4.22026-09-28The modelled cross-platform fallback follows the capability order: a platform with no row for the model is interpolated between the nearest weaker and stronger same-family rows (log-fps over log-TOPS) and sqrt-scaled from the nearest row only outside that range; it was sqrt-scaled from whichever family row came first, so a stronger module could be given less throughput than a weaker module's own row. A derived catalog row (a task figure computed from a detection row by an overhead ratio) is class D, not a measured class C row.
1.4.12026-09-28Input rules (WP-01 remainder, WP-02): cameras / streams are integers (3.5 and true are rejected, never rounded), and both are checked when both are sent; batch_size, detect_fps, motion_share, headroom_target, target_fps, target_latency_ms and precision are checked; precision, batch_size, motion_share, headroom_target, runtime and input_resolution defaults are listed in provenance.defaulted. Unknown input keys are rejected. No formula changed.
1.4.02026-09-27Power mode is a ceiling (highest preset at or below it; none → power_mode_ceiling FAIL, NO FIT; unrecognised → validation error), published as workload.power_mode_request. The calibration factor is relative to the row's own measured mode, so more watts never lower a row. No power mode → the registry default preset (the mode Camera Stream Capacity and Hardware Match use). A resolution with no row is scaled down by the published pixel ratio for a larger input and never scaled up for a smaller one (class D) for detection, segmentation and pose models, and is UNKNOWN for others; no size asked → the row's own size, nothing claimed. The model ladder applies the same rules per model.
1.3.32026-09-20CSC-style model / model_family compact ids (yolo11s → yolo11|s) and streams as the camera-load alias; unknown keys rejected instead of dropped.
1.02026-09-09First release. One throughput resolver using the pessimistic edge of the matching rows, narrowed to the requested batch; class inherited from the rows and demoted on resolution scaling or a power factor; three latency tiers read from a latency_source flag stamped on every row at build time, with both class D tiers able to fail a target but never pass one; the class E headroom target moving the NEAR LIMIT line instead of adding a second constraint; UNSUPPORTED gating the resolver; batch above 1 UNKNOWN without a row; the model ladder in place of any platform recommendation.

Method changes bump the method version; the composite dataset version follows the newest of the registries this engine reads, and every result also carries the per-engine versions in sub_engines.