• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

scikit-hep / iminuit / 33188560776
100%

Build:
DEFAULT BRANCH: develop
Ran 28 Aug 2026 04:19PM UTC
Jobs 1
Files 18
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

28 Aug 2026 04:08PM UTC coverage: 99.617%. Remained the same
33188560776

push

github

web-flow
perf: avoid numpy round-trips in the FCN hot loop (#1136)

:robot: _AI text below_ :robot:

Addresses part of #1132.

## What

The `FCN` object bridges the user's Python cost function into Minuit2
and is called once per minimizer evaluation. Two avoidable numpy
round-trips were happening on that hot path:

1. **`type_caster<std::vector<double>>::load` (`src/pybind11.hpp`)**
converted incoming numpy arrays element-by-element via the Python
iterator protocol, allocating one `np.float64` temporary and running a
per-element cast for every element. Added a fast path: contiguous numpy
arrays are now copied through the buffer protocol with a single
`std::vector::assign`. Non-array sequences still use the generic
iterator path; non-contiguous / non-`double` arrays are normalized via
`c_style | forcecast` (`ensure()` returns null on a genuinely
unconvertible input, so invalid inputs are still rejected).

2. **Scalar (non-array) calling convention (`src/fcn.cpp`)** in
`operator()`, `Gradient`, `G2`, and `Hessian` cast the
`std::vector<double>` to a numpy array (via the custom caster) and
unpacked it as `*args`, so the user function received `np.float64`
scalars. These now build a `py::tuple` of plain Python `float`s
directly, removing an array allocation plus N numpy-scalar allocations
per call. The array-call branches are unchanged (still pass a numpy
array).

## :warning: Behavior-visible change (needs maintainer judgment)

Scalar-mode cost functions now receive **Python `float`** arguments
instead of **`numpy.float64`**. Arithmetic on plain `float` is faster,
and this is generally a non-issue, but any user code that relied on
numpy-scalar behavior (e.g. `.dtype`, numpy-specific methods,
overflow-to-inf instead of `OverflowError`) would see a difference. The
full test suite passes with this change.

## Benchmarks

macOS, CPython 3.13. Median of 7 runs, microseconds per FCN evaluation
(lower is better), measured by repeatedly calling the built `FCN`
directly o... (continued)

3898 of 3913 relevant lines covered (99.62%)

1.0 hits per line

Jobs
ID Job ID Ran Files Coverage
1 33188560776.1 28 Aug 2026 04:19PM UTC 18
99.62
GitHub Action Run
Source Files on build 33188560776
  • Tree
  • List 18
  • Changed 0
  • Source Changed 0
  • Coverage Changed 0
Coverage ∆ File Lines Relevant Covered Missed Hits/Line
  • Back to Repo
  • Github Actions Build #33188560776
  • 50673ac1 on github
  • Prev Build on develop (#31103130412)
  • Next Build on develop (#33206385609)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc