Repository navigation
Moving towards opaque classes: BoolArrayCollection - #214
chrishavlin wants to merge 15 commits into
Conversation
|
thanks for tackling this Chris |
|
oops! left that part out @neutrinoceros ... tagged you and @matthewturk at this stage cause I wanted to double check on the approach here. was thinking of it as a an early proposal PR of sorts? so an in depth review is not required yet, but if you see anything glaringly wrong at this stage definitely let me know! or if you want to wait til I undraft that's fine too. |
neutrinoceros
left a comment
There was a problem hiding this comment.
the approach is definitely sound. I guess my one question at this point is where can I look for documentation about the object type in Cython (or is it c++ ?) ?
|
it's Cython : https://cython.readthedocs.io/en/latest/src/userguide/language_basics.html#python-objects-as-parameters-and-return-values
As I understand it, using a plain |
|
note to self based on some more reading/digging: I should add some strict type checks internally to the api here since moving to an opaque function-based api effectively removes the type checking that would happen during compilation. so if you hand one of these functions the wrong type of object you could get some hard to diagnose errors below the python level (segfaults, other garbage). it's unlikely given that the api will have the methods for getting the proper objects ( |
|
other notes based on experimenting now:
EDIT: implemented both of the above with the initial functions. |
|
ooook. so i wrote a few more of the BoolArrayCollection methods. and then worked through the rest more quickly with claude... at this point, the PR includes everything for |
|
it's reached a size I cannot review efficiently in iterative fashion, so I think we need to coordinate before moving forward. I suggest one of two approaches:
if you want to go with 2, just undraft the PR (and ping me, otherwise I don't think I'll be notified) |
|
yup! good call. i was thinking about taking what I have here now and creating a yt branch to utilize what's in the current c-api here. lemme do that and push up a draft branch to yt then I'll undraft here. I think it will be easier to review with that yt branch in place. this pr as is doesn't cover all of yt's c level ewah calls, but it's enough to demonstrate clearly how to use the new c api. and I think we can do this in stages here too: subsequent PRs for the ewah classes that still need to be covered in the c-api . |
|
oh and one modification that would help I think: im gonna rollback one of the changes here so that I'm only including the methods that yt needs in the c-api. I can add all the ewah class methods later for completeness, but I think for now just having those that yt uses would make sense to keep the prs a bit shorter. |
|
Ok, yt-project/yt#5601 is up! and i noticed more functions on this side that yt doesn't need, so i just removed them. I can pull them from my git history later if we want a complete class mapping to the c-api. |
|
in terms of review and proceeding to other classes: this PR (and subsequent ones) are fine to merge to main since they won't touch internals of the classes and only add new c-api namespaces. So we won't introduce abi incompatibilities if for some reason we need to cut a release before the full c-api is complete. |
|
|
||
| py.install_sources( | ||
| 'src/ewah_bool_utils/capi/__init__.py', | ||
| 'src/ewah_bool_utils/capi/bool_array_collection.pxd', |
There was a problem hiding this comment.
This should probably be in install_data instead. This may work as is but it's a bit confusing; a pyx file isn't a python source
There was a problem hiding this comment.
ok. looking back at my code i'm not sure why i put it in _sources. ya, _data makes more sense and matches what we're doing with the other extension modules. will update!
There was a problem hiding this comment.
moved this to an install_data. note, I also moved 'src/ewah_bool_utils/capi/__init__.py' to ` 'src/ewah_bool_utils/capi/init.pxd' since we have no python API there (and all the module resolution still works without the .py)
| # one cell, one layer of periodic ghosts: 3**3 - 1 neighbours | ||
| assert bac_ghost_zone_count(0, 1, 2) == 26 |
There was a problem hiding this comment.
I'd prefer a more robust impl using symbolic expressions here. Maybe even some parametrization to avoid having a single case passing by accident.
There was a problem hiding this comment.
so i don't mind adjusting these tests some: but for the c-api functions that are purely forwarding functions I'm a bit worried about having to write full tests. IMO they should be testing just the forwarding behavior (does it compile, can we call the method) and not the underlying methods. I know that that there's not a lot of pre-existing tests on the underyling methods, and I do think it'd be good to improve coverage, but I worry about how much that will delay this PR.
There was a problem hiding this comment.
just added a new test function for the second new function introduced by this PR (test_coarse_indices below) and another simple test for the one forwarding function i had missed.
so, opinions on how much I need to beef up the tests of the straight forwarding functions (essentially adding tests for pre-existing functionality that is not currently covered by tests)?
| # one cell, one layer of periodic ghosts: 3**3 - 1 neighbours | ||
| assert bac_ghost_zone_count(0, 1, 2) == 26 | ||
|
|
||
| def test_set_refined_words(self): |
There was a problem hiding this comment.
Without knowning anything about the api under test, this test is practically meaningless to me as a reader. It may be fine, maybe I just need to understand the api, but I really like tests that can teach the reader about it when feasible
There was a problem hiding this comment.
(or make the tests more self descriptive)
There was a problem hiding this comment.
ooook, rewrote and beefed this one up. now got:
- a helper function that does what yt does when it wants to mark a sub-cell as refined so i'm not writing out bits manually
- parametrization of which cells to refine and how that corresponds to the bit-indices
- lots more comments and renamed variables for clarity
| return out_arr | ||
|
|
||
|
|
||
| def bac_new() -> object: |
There was a problem hiding this comment.
I don't get the intention behind these functions, they look like an additional wrapping layer on top of the one you're building and actively testing
There was a problem hiding this comment.
just so they can be called from tests: without them from pytest we'd have to call the python api which would never hit the new c-api.
There was a problem hiding this comment.
note, i looked into using cython.inline or compiling _testing.pyx as part of the pytest config... and things got complicated. cython.inline is a bit out dated and we'd need to add a setuptools dependency for python 3.12+ to the test stuie, pytest config didn't seem any less complicated that what we're doing now.
|
pre-commit.ci autofix |
for more information, see https://pre-commit.ci
Update: this implements just the
BoolArrayCollectionc-api. Related to #216This is a draft PR with a couple of small implementations of enforcing opaque classes via a new C api. It's much smaller than the full implementation would be, but I think hits the functional changes and clarifies how we'd have to update yt.I've been relying on claude a bit to understand the problem better and what potential solutions there are, but words and implementation here are all my own.
origin of the build compatibility problems
as far as I understand it, the underlying issue is that when yt cimport's the ewah_bool classes, yt has to carry a copy of ewah_bool's internal object layout. So changes in Cython version, build settings, etc. on either side create a mismatch that can lead to import errors (yt-project/yt#5232).
the proposed fix: a wrapper
apiThe gist is that if we write a bunch of wrapper functions that accept an instantiated ewah_bool classes typed as a plain
objectthat are cast to their appropriate ewah classes internally in the api, then yt would never have to cimport the cdef classes, reach into class attributes or touch C++ types.e.g., in
api.pyx, we have:and the yt side would be updated to use the new api functions only. e.g.,
instead of the current state:
One important limitation: these wrapper functions should not rely on numpy ctypes or buffer as it would re-introduce a point of incompatibility. So
libc.stdinttypes have to be used along with typed memoryviews.scope and transition
The minimum change is to add wrapper functions in
api.pyxfor all the functions used by yt'sparticle_oct_container.pyx. once they exist, we can release ewah_bool_utils 1.4.0 and then update yt to use the new functions in 4.5.0. ewah_bool_utils 2.0 could stop shipping ewah_bool_wrap.pxd. We'd need around 40 functions inapi.pyxto cover just yt's uses -- if we want to expand to cover the whole ewah_bool_utils package (which we probaby should?), it's closer to 100 functions.Note that the vast majority of api functions would be pretty simple one or two line forwarding functions, but there are a few sections in
particle_oct_container.pyxthat would require new functions on the ewah_bool_utils api side -- i.e.,bool_array_collection_coarse_indicesin this PR would get used inhttps://github.com/yt-project/yt/blob/51c862ab474af6ed005a5d7cc6956539e308dd8f/yt/geometry/particle_oct_container.pyx#L370-L399
(and a couple other similar spots).
ai disclosure
been using claude for understanding how to do this... implementations are my own though. can discuss if this would qualify as a good use of AI to build out the new api in one go.