Skip to content

perf(predictor): use less memory while keeping identical detections - #427

Open
frgfm wants to merge 2 commits into
developfrom
perf/reduce-inference-allocations
Open

frgfm wants to merge 2 commits into
developfrom
perf/reduce-inference-allocations

Conversation

@frgfm

@frgfm frgfm commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Preparing a frame made extra image copies. Checking overlapping boxes built one huge table. This keeps the copies we need, joins frame history once, and checks overlaps 128 rows at a time.

flowchart LR
    subgraph Before
        A[Extra image copies] --> B[One huge overlap table]
    end
    subgraph After
        C[Fewer image copies] --> D[Small batches of rows]
    end
    B --> E[Same detections]
    D --> E
Loading

Both NCNN and ONNX use these image/box changes. Defaults stay unchanged.

Workload Time before → after (ms) Peak memory before → after (MiB)
1080p frame preparation 17.60 → 9.85 153.8 → 107.0
Suppression, 4,096 boxes (stress test) 799.71 → 129.32 578.5 → 86.3
4K NCNN Engine, default settings 378.1 → 359.0 874.3 → 819.2
4K ONNX Engine, default settings 422.1 → 435.4 568.9 → 535.7
4K ONNX Engine, opt-in tuning 422.1 → 345.0 568.9 → 357.0

Medians of three fresh processes against dbf298d; CPU-only EPYC 9V74, four-CPU quota. Last row uses intra_op_num_threads=4 and enable_mem_pattern=False. Runtime timings varied; Pi/ARM needs a device run.

Same answers on real photos: compared dbf298d with ab14f8d on Pyro-SDIS.

Backend Photos with model inputs compared Full inference pairs Differences
NCNN 1,129 256 0
ONNX 1,129 256 0

For each photo, old and new code produced identical input tensors. Full inference also matched boxes, scores, temporal alert state and JPEGs exactly. Fixed weights, CPU/four threads, 720p Engine input, subset seed 427. This checks regression agreement. Run and raw results (artifact: pr427-real-image-comparison).

ONNX options: the existing Engine → Predictor → Classifier path forwards onnx_session_options through **kwargs; an Engine-level test now verifies it reaches ONNX Runtime.

Checks: 13 focused regression cases; test file reduced from 175 to 73 lines. GitHub CI passed 76 engine tests and 82 camera API tests (seven skipped). All five PR workflows passed.

The isolated comparison branch was removed. Its workflow/data are outside this PR's history; the diagram lives only in this description.

@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.48%. Comparing base (dbf298d) to head (ab14f8d).
⚠️ Report is 3 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #427      +/-   ##
===========================================
+ Coverage    79.46%   79.48%   +0.02%     
===========================================
  Files            6        6              
  Lines          852      853       +1     
===========================================
+ Hits           677      678       +1     
  Misses         175      175              
Flag Coverage Δ
unittests 79.48% <100.00%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@frgfm frgfm self-assigned this Oct 7, 2026
@MateoLostanlen
MateoLostanlen self-requested a review October 8, 2026 15:11
@MateoLostanlen

Copy link
Copy Markdown
Member

Thanks, nice work @frgfm . The letterbox / RGB / pool changes are simple and the memory gain is welcome.

  • We also run on servers, so the ONNX path matters too. onnx_session_options is not wired though: Predictor builds the Classifier without it, so Engine can't use it. Either remove it or pass it through Predictor and Engine.
  • Did you check that outputs are identical on real images, not only synthetic ones? Could you run base vs this branch on a batch of images from https://huggingface.co/datasets/pyronear/pyro-sdis (ncnn and onnx) and compare the predictions?
  • The test file is quite heavy since it keeps copies of the old implementations. I'd keep the overlap chain test, one letterbox equivalence test and the RGB test, and drop the rest

@frgfm

frgfm commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

Thanks, nice work @frgfm . The letterbox / RGB / pool changes are simple and the memory gain is welcome.

* We also run on servers, so the ONNX path matters too. `onnx_session_options` is not wired though: `Predictor` builds the `Classifier` without it, so Engine can't use it. Either remove it or pass it through `Predictor` and `Engine`.

* Did you check that outputs are identical on real images, not only synthetic ones? Could you run base vs this branch on a batch of images from https://huggingface.co/datasets/pyronear/pyro-sdis (ncnn and onnx) and compare the predictions?

* The test file is quite heavy since it keeps copies of the old implementations. I'd keep the overlap chain test, one letterbox equivalence test and the RGB test, and drop the rest

All addressed :)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants