Skip to content

EagerJAXArrayContext: return mutable numpy array in to_numpy #315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

matthiasdiener
Copy link
Collaborator

@matthiasdiener matthiasdiener commented May 23, 2025

AFAICS, there is no way to make an immutable numpy array mutable again except for copying it.

@matthiasdiener matthiasdiener self-assigned this May 23, 2025
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR modifies the to_numpy method in the JAX array context to return a mutable NumPy array by explicitly copying the result of jax.device_get.

  • Wraps jax.device_get result in np.copy to produce a writable array.
Comments suppressed due to low confidence (1)

arraycontext/impl/jax/init.py:104

  • The code uses np.copy but numpy is not imported in this scope, which will raise a NameError. Add import numpy as np at the module level or within the function.
return np.copy(jax.device_get(ary))

@alexfikl
Copy link
Collaborator

I'm a bit out of the loop, so I have questions 😁

  1. Why is this required? To my knowledge, most of the code doesn't do in-place modifications (e.g. DOFArray in-place operations are very deprecated).
  2. Haven't tested, but jax.device_get docs mention copies being done. Is that not the case?
  3. Would this be useful when using the CPU backend for jax? I image the GPU/TPU backends do a copy anyway?

@matthiasdiener
Copy link
Collaborator Author

matthiasdiener commented May 27, 2025

Thanks for the review @alexfikl !

  1. Why is this required? To my knowledge, most of the code doesn't do in-place modifications (e.g. DOFArray in-place operations are very deprecated).

There are in-place modifications in grudge, e.g. grp_field in https://github.com/inducer/grudge/blob/193100abd566719b26001b85feb3d7d2171f5b8d/grudge/geometry/metrics.py#L567-L577

Without this PR, some tests in grudge with Jax fail (see e.g. inducer/grudge#380).

  1. Haven't tested, but jax.device_get docs mention copies being done. Is that not the case?
  2. Would this be useful when using the CPU backend for jax? I image the GPU/TPU backends do a copy anyway?

I think there are copies done, both for CPU and GPU, the problem is that jax.device_get returns an immutable numpy array (i.e., ary.flags.WRITEABLE is set to False). As far as I can tell, the only way around that is to make another copy, as in this PR. If ary.flags.WRITEABLE is already set to False, numpy refuses to set the flag back to True.

@alexfikl
Copy link
Collaborator

alexfikl commented May 27, 2025

There are in-place modifications in grudge, e.g. grp_field in inducer/grudge@193100a/grudge/geometry/metrics.py#L567-L577

I remember writing some version of that code.. it should really be rewritten in a nicer way :(

But fair enough, I can see how that breaks. Are there any other places? (the tests in inducer/grudge#380 seem to be passing nicely at the moment)

EDIT: It wasn't running tests with jax, I see them now! 😁

@matthiasdiener matthiasdiener marked this pull request as ready for review May 27, 2025 23:32
Copy link
Collaborator

@alexfikl alexfikl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would personally prefer if this gets fixed in grudge, since it's just that one place that seems to fail (?). Doing two copies on to_numpy here seems like a hack.

If we do go for it, we should also document it somewhere that the arrays returned by to_numpy are writable, since it's apparently not a given!

@matthiasdiener matthiasdiener marked this pull request as draft May 28, 2025 21:36
@matthiasdiener
Copy link
Collaborator Author

I would personally prefer if this gets fixed in grudge, since it's just that one place that seems to fail (?). Doing two copies on to_numpy here seems like a hack.

I agree, and I've just added a (sketchy) reimplementation in inducer/grudge#380, feel free to take a look. Setting this PR back to draft.

If we do go for it, we should also document it somewhere that the arrays returned by to_numpy are writable, since it's apparently not a given!

Right, either way of what happens with this PR, we should document this in to_numpy.

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