Skip to content

SubTracker: Move static variables into a struct and access them via PyModule_GetState. #31930

Open

Description

@prathamhole14

Long Term Effort Tracker: #31913

Module Status Link
lapack_lite Done #31928
_multiarray_umath State moved, still accessed through the global _npy_module_state pointer #31992, #32544
_pocketfft_umath _simd, _multiarray_tests _umath_linalg No change needed —
random (9 Cython modules) Out of scope —
_rational_tests Done #32456

TODO

Activity

  1. ngoldbaum commented on Jul 9, 2026

    @ngoldbaum
    Member

    For these subtracker issues I'd like to see a bit more detail about what you're planning to do in the description.

  2. da-woods commented on Jul 12, 2026

    @da-woods
    Contributor

    You probably already know this (in that I'm sure you've thought about it more than me), but I think you have some "fun" to come with import_array().

    I think you need to fix both sides of it, in that

    1. The macro uses a C global static void** as your array API table (rather than a pointer in the module state).
    2. Ultimately it'll need to point to per-interpreter types rather than static types.
  3. prathamhole14 commented on Jul 13, 2026

    @prathamhole14
    MemberAuthor

    Hi everyone!
    This is a high level overview of how I plan to migrate to module-level state for the _multiarray_umath module.

    1. Infrastructure set up containing these 5 structs and other scattered global variables (zero functional changes).
      A : Add to the bottom of npy_static_data.h - No change header file import
      B : Create a new module_state.h in multiarray - Clean in one single
      I prefer option B but please let me know what you think.

    2. Migration PR for each struct npy_interned_str_struct, npy_static_pydata_struct, npy_static_cdata_struct ,npy_runtime_imports_struct, npy_global_state_struct.
      To keep the PRs for the larger structs easy to review, I plan to temporarily use a global pointer _npy_module_state to access the module state. This avoids having to thread the state pointer through dozens of deep call chains in a single PR. We can remove the transitional global pointer once all migrations are complete.
      Temporary global pointer like multiarray_umath_state *_npy_module_state = NULL

    3. Migration of other scattered globals just like structs.
      This is high level of how I am planning to proceed, please let me know what you think then I will start creating PRs one by one.

    CC: @mattip @ngoldbaum @rgommers @da-woods

  4. ngoldbaum commented on Jul 13, 2026

    @ngoldbaum
    Member

    Are there still mutable globals scattered in the NumPy implementation? I thought I got all of them for free-threading support.

  5. prathamhole14 commented on Jul 14, 2026

    @prathamhole14
    MemberAuthor

    Yeah, there are still a few scattered globals left PyDataMem_DefaultHandler, current_handler, uo_index and typeDict (I took help from AI to find them). I think they were probably left as process-globals during the free-threading work because they're read-only and thread-safe

  6. ngoldbaum commented on Jul 14, 2026

    @ngoldbaum
    Member

    Ah it wasn’t clear to me you need to do this for immutable globals too. Thanks.

  7. prathamhole14 commented on Jul 14, 2026

    @prathamhole14
    MemberAuthor

    Should the infrastructure PR include all 5 struct fields upfront (with FIXME notes), or should I add each field only in the PR that migrates it? If we add all 5 in one, the benefit is other PRs can be made without worrying about merge conflicts, but the disadvantage will be: until everything is shifted, "dead" code will be present in numpy for some time

    Hi everyone! This is a high level overview of how I plan to migrate to module-level state for the _multiarray_umath module.

    1. Infrastructure set up containing these 5 structs and other scattered global variables (zero functional changes).
      A : Add to the bottom of npy_static_data.h - No change header file import
      B : Create a new module_state.h in multiarray - Clean in one single
      I prefer option B but please let me know what you think.
    2. Migration PR for each struct npy_interned_str_struct, npy_static_pydata_struct, npy_static_cdata_struct ,npy_runtime_imports_struct, npy_global_state_struct.
  8. ngoldbaum commented on Jul 14, 2026

    @ngoldbaum
    Member

    In that case I’d prefer to do it all in one PR. Others may disagree with me though.

  9. mattip commented on Jul 14, 2026

    @mattip
    Member

    I think this is small enough to do in one PR. I am worried about the viability of moving the API table into a module struct, if we discover that it is not straight-forward we may have to revisit the idea of a single PR. If we decide to give up on some of the global data, we can clean up the dead code later on.

  10. prathamhole14 commented on Jul 14, 2026

    @prathamhole14
    MemberAuthor

    @ngoldbaum and @mattip thank you for helping with decision making. Please checkout #31992

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions