Repository navigation
Copy DoubleVector and IntVector data to numpy arrays in C++ - #3524
Open
FFroehlich wants to merge 1 commit into
Open
FFroehlich wants to merge 1 commit into
FFroehlich wants to merge 1 commit into
Conversation
numpy has no buffer or array interface for the SWIG proxies of std::vector, so `np.array(vec)` built the array from the proxy's Python iterator, one element at a time. `ReturnDataView` converts every field this way, which took tens of milliseconds for `x` or `w` of a medium model and, e.g., more time than the simulations themselves for the FIMs of a PEtab problem with many experiments. Give `DoubleVector` and `IntVector` an `__array__` method which copies the data into a new array in C++. The wrapper keeps the GIL, since the extension is built with `-threads`. Fixes #3510. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## claude/issue-3521-cache-edatas #3524 +/- ##
==================================================================
- Coverage 80.30% 80.24% -0.07%
==================================================================
Files 331 331
Lines 23434 23434
Branches 1631 1631
==================================================================
- Hits 18819 18804 -15
- Misses 4609 4624 +15
Partials 6 6
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this pull request do, and why?
Makes
numpy.array/numpy.asarrayof aDoubleVectororIntVectorcopy the data in C++, instead of building the array element by element from the vector proxy's Python iterator. That per-element conversion is whatReturnDataViewdoes for every field it returns (np.array(attr).reshape(field_dim)in_field_as_numpy), so it was paid after every simulation forx,w,y,sx,FIM, and so on.DoubleVectorandIntVectorget a__array__(dtype=None, copy=None)method. It calls a new_to_ndarraymethod, implemented in C++ in%extend, which allocates a 1D array and copies the data withmemcpy(float64) orstd::copy(int64, the same dtypenp.array(IntVector)gave before)._to_ndarraycreates Python objects, so its wrapper must keep the GIL. The extension is built with-threads, which releases the GIL around every wrapped call, so_to_ndarraygets%feature("nothreadallow"). I checked in the generated wrapper that its call has noSWIG_PYTHON_THREAD_BEGIN_ALLOW(unlike, e.g.,DoubleVector.__len__andstdVec2ndarray, see below).ReturnDataalive. Thereforenp.asarray(vec, copy=False)raisesValueError, as the numpy protocol requires when a copy can't be avoided. NumPy 2 passescopy=Trueto__array__fromnp.arrayand then doesn't copy again (checked), so_field_as_numpyis unchanged.Timings on this Mac (Python 3.13, numpy 2.5.4), this branch vs. a build of #3520's head:
np.array(DoubleVector), 123,000 elements (wof 82 expressions at 1500 time points, from the issue)np.array(IntVector), 123,000 elements_field_as_numpyof a 46×46FIM, 18,338 times (the PEtab v2_aggregate_s2llhcase from the issue comment)Not run on the Froehlich_CellSystems2018 problem or in sbmlsim.
Not addressed here:
stdVec2ndarraystill releases the GIL (stdVec2ndarraysegfaults: the SWIG wrapper releases the GIL around a function which creates a numpy array #3509), andDoubleVector[i]still raises aTypeErrorafterimport amici(DoubleVector[i]andIntVector[i]raise a TypeError afterimport amici: libsbml is loaded before the extension and its SWIG types win #3511). This PR uses neither.XArrayFactory.__init__while creating 18,338ReturnDataViews, possibly cyclic garbage collection (eachReturnDataViewand itsXArrayFactoryreference each other). Not investigated here.This is stacked on #3522, but doesn't depend on its changes.
Testing:
test_vector_to_ndarrayinpython/tests/test_swig_interface.py: replaces__iter__ofDoubleVectorandIntVectorwith a function that raises, then checks values, dtypes, shapes, that the arrays are copies,dtype=,copy=False, empty vectors,repr, and thex,sx,y, andnumstepsfields of aReturnDataViewagainst the element-wise conversion. Fails on Make PEtab v2 ExperimentManager lookups constant-time #3520's head ("converted via the Python iterator"), passes here.test_swig_interface.py,test_rdata.py,test_edata.py,test_hdf5.py,test_sbml_import.py, andpetab_/test_petab_v2.py: 115 passed, 7 skipped (not checked why). The 7 JAX tests intest_petab_v2.pydidn't run, since JAX/diffrax isn't installed in this environment.test_fiddy_derivative_check_leaves_solver_unchangedneeds fiddy from git (--group python/sdist/pyproject.toml:fiddy); it passes with it.Related issues
Fixes #3510
Use of AI tools
Claude Code (Claude Opus 5.5) wrote the implementation, the test, the changelog entry, and this description, and ran the tests and timings described above.
Checklist
changelog.d/(or it is not needed)🤖 Generated with Claude Code