Skip to content

Use pytorch as backend for xarrays #3232

Open

Description

@fjanoos

I would be interested in using pytorch as a backend for xarrays - because:
a) pytorch is very similar to numpy - so the conceptual overhead is small
b) [most helpful] enable having a GPU as the underlying hardware for compute - which would provide non-trivial speed up
c) it would allow seamless integration with deep-learning algorithms and techniques

Any thoughts on what the interest for such a feature might be ? I would be open to implementing parts of it - so any suggestions on where I could start ?

Thanks

Activity

  1. shoyer commented on Aug 20, 2019

    @shoyer
    Member

    If pytorch implements overrides of NumPy's API via the __array_function__ protocol, then this could work with minimal effort. We are already using this to support sparse arrays (this isn't an official release yet, but functionality is working in the development version).

    I think there has been some discussion about this, but I don't know the current status (CC @rgommers). The biggest challenge for pytorch would be defining the translation layer that implements NumPy's API.

    Personally, I think the most viable way to achieve seamless integration with deep learning libraries would be to support integration with JAX, which already implements NumPy's API almost exactly. I have an experimental pull request adding __array_function__ to JAX, but it still needs a bit of work to finish it up, e.g., we probably want to hide this behind a flag at first.

  2. rgommers commented on Aug 20, 2019

    @rgommers

    I think there has been some discussion about this, but I don't know the current status (CC @rgommers).

    The PyTorch team is definitely receptive to the idea of adding __array_function__ and __array_ufunc__, as well as expanding the API for better NumPy compatibility.

    Also, they want a Tensor.__torch_function__ styled after __array_function__ so they can make their own API overridable.

    The tracking issue for all of this is pytorch/pytorch#22402

    The biggest challenge for pytorch would be defining the translation layer that implements NumPy's API.

    Agreed. No one is working on __array_function__ at the moment. Implementing it has some backwards compat concerns as well, because people may be relying on np.somefunc(some_torch_tensor) to be coerced to ndarray. It's not a small project, but implementing a prototype with a few function in the torch namespace that are not exactly matching the NumPy API would be a useful way to start pushing this forward.

  3. rgommers commented on Aug 20, 2019

    @rgommers

    Personally, I think the most viable way to achieve seamless integration with deep learning libraries would be to support integration with JAX, which already implements NumPy's API almost exactly.

    Less familiar with that, but pytorch does have experimental XLA support, so that's a start.

  4. shoyer commented on Aug 20, 2019

    @shoyer
    Member

    Implementing it has some backwards compat concerns as well, because people may be relying on np.somefunc(some_torch_tensor) to be coerced to ndarray.

    Yes, this is a concern for JAX as well. This is a definite downside of reusing NumPy's existing namespace.

    It turns out even xarray was relying on this behavior with dask in at least one edge case: #3215

  5. rgommers commented on Aug 20, 2019

    @rgommers

    This is a definite downside of reusing NumPy's existing namespace.

    We didn't discuss an alternative very explicitly I think, but at least we'll have wide adoption fast. Hopefully the pain is limited ....

  6. fjanoos commented on Aug 23, 2019

    @fjanoos
    Author

    I haven't used JAX - but was just browsing through its documentation and it looks super cool. Any ideas on how it compares with Pytorch in terms of:

    a) Cxecution speed, esp. on GPU
    b) Memory management on GPUs. Pytorch has the 'Dataloader/Dataset' paradigm which uses background multithreading to shuttle batches of data back and forth - along with a lot of tips and tricks on efficient memory usage.
    c) support for deep-learning optimization algorithms ?

  7. shoyer commented on Aug 23, 2019

    @shoyer
    Member

    Within a jit compiled function, JAX's execution speed should be quite competitive on GPUs. It uses the XLA compiler, which was recently enabled by default in TensorFlow.

    For data loading and deep learning algorithms, take a look at the examples in the notebooks directory in the JAX repo. The APIs for deep learning in JAX are still undergoing rapid development, so APIs are not quite as stable/usable as pytorch or keras yet, but they are quite capable. See jax.experimental.stax and tensor2tensor.trax for examples.

  8. fjanoos commented on Aug 23, 2019

    @fjanoos
    Author

    While it is pretty straightforward to implement a lot of standard xarray operations with a pytorch / Jax backend (since they just fallback on native functions) - it will be interesting to think about how to implement rolling operations / expanding / exponential window in a way that is both efficient and maintains differentiability.

    Expanding and exponential window operations would be easy to do leveraging RNN semantics - but doing rolling using convolutions is going to be very inefficient.

    Do you have any thoughts on this?

  9. shoyer commented on Aug 23, 2019

    @shoyer
    Member
  10. fjanoos commented on Mar 30, 2020

    @fjanoos
    Author

    This might be a good time to revive this thread and see if there is wider interest (and bandwidth) in having xarray use CuPy (https://cupy.chainer.org/ ) as a backend (along with numpy). It appears to be a plug-and-play replacement for numpy - so it might not have all the issues that were brought up regarding pytorch/jax ?

    Any thoughts ?
    cc @mrocklin

  11. dcherian commented on Mar 30, 2020

    @dcherian
    Contributor

    Just chiming in quickly. I think there's definitely interest in doing this through NEP-18.

    It looks like CUDA has implemented __array_function__ (https://docs-cupy.chainer.org/en/stable/reference/interoperability.html) so many things may "just work". There was some work earlier on plugging in pydata/sparse, and there is some ongoing work to plug in pint. With both these efforts, a lot of xarray's code should be "backend-agnostic" but its not perfect.

    Have you tried creating DataArrays with cupy arrays yet? I would just try things and see what works vs what doesn't.

    Practically, our approach so far has been to add a number of xfailed tests (test_sparse.py and test_units.py) and slowly start fixing them. So that's one way to proceed if you're up for it.

  12. jhamman commented on Mar 30, 2020

    @jhamman
    Member

    @jacobtomlinson gave CuPy a go a few months back. I seem to remember that he ran into a few problems but it would be good to get those documented here.

  13. jakirkham commented on Mar 30, 2020

    @jakirkham

    Yeah Jacob and I played with this a few months back. There were some issues, but my recollection is pretty hazy. If someone gives this another try, it would be interesting to hear how things go.

  14. fjanoos commented on Mar 31, 2020

    @fjanoos
    Author
  15. jakirkham commented on Mar 31, 2020

    @jakirkham

    Well here's a blogpost on using Dask + CuPy. Maybe start there and build up to using Xarray.

  16. 25 remaining items

  17. tomwhite commented on Jul 13, 2022

    @tomwhite
    Contributor

    I started having a look at making xarray work with the array API here: tomwhite@c72a1c4. Some basic operations work (preserving the underlying array): tomwhite@929812a. If there's interest, I'd be happy to turn this into a PR with some tests.

  18. dcherian commented on Jul 13, 2022

    @dcherian
    Contributor

    I'd be happy to turn this into a PR with some tests.

    Absolutely!

  19. tomwhite commented on Jul 18, 2022

    @tomwhite
    Contributor

    Opened #6804

  20. hsharrison commented on Jul 20, 2022

    @hsharrison
    Contributor

    Glad to see progress on this!! 👏

    Just curious though, seeing this comment in the PR:

    Note: I haven't actually tested this with pytorch (which is the motivating example for #3232).

    Are we sure this closes the issue? And, how can we try it out? Even lacking docs, a comment explaining how to set it up would be great, and I can do some testing on my end. I understand that it's an experimental feature.

  21. tomwhite commented on Jul 20, 2022

    @tomwhite
    Contributor

    Hi @hsharrison - thanks for offering to do some testing. Here's a little demo script that you could try, by switching numpy.array_api to pytorch: tomwhite@929812a

  22. hsharrison commented on Jul 20, 2022

    @hsharrison
    Contributor

    Nice that it's so simple. I think it can't be tested with pytorch until they compete pytorch/pytorch#58743, right?

    Or we should just try passing torch.tensor into xarray directly?

  23. tomwhite commented on Jul 20, 2022

    @tomwhite
    Contributor

    I think it can't be tested with pytorch until they compete pytorch/pytorch#58743, right?

    It needs __array_namespace__ to be defined to activate the new code path.

  24. hsharrison commented on Jul 20, 2022

    @hsharrison
    Contributor

    Makes sense, then I'll wait for pytorch/pytorch#58743 to try it.

  25. reopened this on Jul 20, 2022
  26. jakirkham commented on Jul 20, 2022

    @jakirkham

    While it is true to use PyTorch Tensors directly, one would need the Array API implemented in PyTorch. One could use them indirectly by converting them zero-copy to CuPy arrays, which do have Array API support

  27. cshuphys commented on Dec 31, 2025

    @cshuphys

    Even after define __array_namespace__ to torch.Tensor, there could be occasionally RuntimeError trigger for checking hasattr(torch.Tensor, "imag"). Minimal example to reproduce the problem is follows.

    # Python 3.11.7, xarray 2025.12.0, Torch 2.9.1, numpy 2.2.6
    import array_api_compat.torch as xp_torch
    import torch
    import xarray as xr
    
    torch.Tensor.__array_namespace__ = lambda self, **kwargs: xp_torch
    da = xr.DataArray(torch.zeros, coords=dict(x=[0], y=[1, 2]))
    print(f"Underlying type: {type(da.data)}")
    
    print(da.data.dtype)
    
    da.data[0, 0] += 1
    print(da)
    print(type(da.sum().data))
    print(type(da.sel(x=0).data))
    print(da.transpose("y", "x"))
    

    It occassionally triggers bug

    Traceback (most recent call last):
    File "", line 99, in <module>
        print(type(da.sum().data))
    File "./.venv/lib/python3.11/site-packages/xarray/core/_aggregations.py", line 3167, in sum
        return self.reduce(
               ^^^^^^^^^^^^
    ...
    File "./.venv/lib/python3.11/site-packages/xarray/namedarray/core.py", line 205, in from_array
        if isinstance(data, _arrayfunction_or_api) and not isinstance(data, np.generic):
    File "./lib/python3.11/typing.py", line 2006, in __instancecheck__
        if all(hasattr(instance, attr) and
    RuntimeError: imag is not implemented for tensors with non-complex dtypes.
    

    The randomness is from _get_protocol_attrs(cls) in typing.py is using a set. Thus torch.Tensor.imag can raise exception if imag is checked first. A quick work around is to overwrite torch.Tensor.imag to allow it return None for non-complex tensor. Another way is to switch check order in xarray at xarray/namedarray/_typing.py to check array api first

    _arrayfunction_or_api = (_arrayfunction, _arrayapi) 
    
  28. shoyer commented on Jan 1, 2026

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions