NumPy array protocols #771
Replies: 19 comments
-
Scikit-Learn developers are taking a look at NEP-37 vs. NEP-18: scikit-learn/scikit-learn#17676 |
Beta Was this translation helpful? Give feedback.
-
Thanks @oleksandr-pavlyk. There's more discussion on that in scikit-learn/scikit-learn#16574, and in the meeting minutes linked above (last link under References). |
Beta Was this translation helpful? Give feedback.
-
@rgommers Thanks for this useful summary. Do you know if SciPy has any discussions/plans similar to scikit-learn/scikit-learn#16574 ? There are several efforts reimplementing SciPy:
A natural question is, given NEP-18/NEP-37, could I simply copy-and-paste their code, to provide SciPy API on top of other frameworks such as PyTorch/MXNet/TVM? My current answer is NO, due to the following reasons:
Among all SciPy APIs, those submodule seems extremely useful:
Those are also quite useful:
If those APIs can be reimplemented in pure NumPy, and ported to other AI frameworks like MXNet/PyTorch (via NEP-37), we will automatically get the parallel version of all those solvers with end-to-end autodiff functionality. Sounds like a very big deal :) |
Beta Was this translation helpful? Give feedback.
-
Yes, there are some plans. For submodules that are mostly compiled code, it makes sense that there are reimplementations, and it would be good if SciPy became aware of those. A discussion for For higher-level Python (and maybe Cython) code like in
Sparse is a bit of a special case. There are exactly zero sparse ndarray/tensor implementations that anyone is happy with. So thinking about dispatching/reuse of code, whether in |
Beta Was this translation helpful? Give feedback.
-
@rgommers Thanks for the replies. Regarding sparse matrix and its operations, I feel that PyTorch has decent support -- see pytorch_sparse and pytorch_scatter, which are used by the pytorch_geometric GNN library. The question then is, how should existing sparse tensor backends map to numpy/scipy? Candidates include:
etc... |
Beta Was this translation helpful? Give feedback.
-
Not yet - a 2-D CSR implementation only just landed in PyTorch (will be released in 1.9.0) and that still lacks support in many operators. And its COO implementation is super slow. The third-party implementations are even more incomplete I believe.
What we need is a sparse ndarray with the exact same API as |
Beta Was this translation helpful? Give feedback.
-
This is exactly the reason why I bring up the third party |
Beta Was this translation helpful? Give feedback.
-
I totally agree that Pydata Sparse API is most consistent with N-D sparse tensor is indeed useful, but its use cases rarely come from scientific computing (the main use case of SciPy), but instead come from sparse neural networks in AI (see apache/tvm#4332). For now, AI models rarely use truly sparse N-D tensors (N ≥ 3). Graph Neural Networks simply need a 2-D sparse matrix to express connectivity. Sparsified/pruned neural networks (similar to model compression & quantization) are often limited to block-sparse patterns, with 4x4/8x8 small dense blocks to match GPU's SIMT architecture. Sparse tensors are also incompatible with the systolic array architecture used by Google TPU and AWS Inferentia, furthur limiting their wide usage in AI. Given the above facts, a natural question is: “is it worthwhile to fully support arbitrary-dimension sparse tensors, given their relatively limited usage?“ The most useful component in Maybe we just need to fix the annoying |
Beta Was this translation helpful? Give feedback.
-
That does not align with my experience. At least from computational physics, having sparse tensors backing a quantum tensor network calculation is very useful. From the most simple matrix product state/tensor train to more sophisticated TN constructions, we can almost always make use of a rank > 2 sparse tensor representation at least for the most common short-range interactions.
I'd say yes. There are emerging needs for this capacity.
Even taking a step back from tensor networks, having an ndarray backed by sparse tensors is useful to express batched SpMV and SpMM operations, for example, which in turn allow an efficient construction of the batched version of the solvers you mentioned. I have heard in several different occasions recently that people wish for such capability. If there is a sparse ndarray, it can help such needs very naturally. Of course even for GPUs there are quite some work to be done, but I think the investigation has already begun. |
Beta Was this translation helpful? Give feedback.
-
Those are all good points that I am not against to. To rephrase my opinion -- it is indeed necessary to support N-D sparse tensors in the next-generation NumPy/SciPy ecosystem -- the current PyData Sparse library and the sluggish Broadcasting over arbitrary-dimension sparse tensors leads to performance optimization difficulties, and there will always be people complaining about the performance of My argument is, given the wide usage of 2-D sparse matrix, won't it be a low-hanging fruit to first design a good-enough 2-D sparse matrix abstraction, to facilitate the development of distributed/accelerated/differentiable versions of commonly used solvers in HPC? Batched SpMV and SpMM operations can be implemented by 2-D sparse matrix + 1-D extension (3-D in total), and don't necessarily need 100-dimension sparse tensors. |
Beta Was this translation helpful? Give feedback.
-
Further speaking of HPC use cases, considering the two biggest domains in traditional HPC -- fluid mechanics (weather, climate, engineering) and molecular dynamics (chemistry, biology, combustion). Those physical problems are typically discretized into 3-D/higher dense arrays (to represent physical fields) and 2-D sparse matrices (to present linear operators / physical interactions). For more complicated numerical algorithms like adaptive mesh refinement (AMR), more advanced data structures are needed -- such as KD-tree for nearest neighbor search. Having a perfect N-D sparse tensor library still can't solve this area of problems. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the thoughts @learning-chip and @leofang. I think there's something to say for both viewpoints, they don't really conflict. In terms of number of use cases: There's two related but separate issues here:
(1) is easier: the semantics should match those of dense/arrays tensors, and that statement is independent of the dimensionality of use cases. For (2), SciPy is 2-D only, PyTorch just added 2-D CSR (a lot faster than COO) and is moving to extensions like batched 2-D and block-sparse.
That would be great, but it's hard to do given backwards compat issues. It will require a new API. For other efforts, the main thing is to ensure they don't copy SciPy's design mistake. PyData Sparse is ambitious going for n-D straight away, we'll see if they can pull it off.
I'm not sure how much a change in SciPy would influence the API of PyTorch/TF/JAX/MXNet - I hope not at all. |
Beta Was this translation helpful? Give feedback.
-
All agreed!
This is the exact question I want to ask -- for someone designing a new SciPy-like solver suite, what should the new API like? What are the design mistakes we must avoid? The current best reference for me is From a compiler point of view, TACO SpMV is a very good reference for optimizing sparse operations. But how should it map to NumPy/SciPy frontend remains a question, and I hope to get some thoughts/advice here. |
Beta Was this translation helpful? Give feedback.
-
Isn't this just The sparse-specific API should only be constructing the sparse arrays, after that it can follow this array API standard (or numpy, or pytorch, or ... - all equivalent here).
This will be the same answer - constructing batched/block-sparse will need specific constructor functions, and then it should be able to use the dense API. |
Beta Was this translation helpful? Give feedback.
-
Yes, for just SpMV. If the goal is just to build another CuPyx-like solver library (backed by one of PyTorch/MXNet/TVM for example), then changing
My questions right now:
Same question for accelerated sklearn. I will see if sklearn-onnx is the right solution. |
Beta Was this translation helpful? Give feedback.
-
Not about a standard as such. I think to consider that, we first need to show the array API standard being adopted and used in SciPy and other downstream libraries. It's also a much more fuzzy question - it may make sense for some parts of SciPy but not for the package as a whole. For For the most widely used functions in
I can't disagree with that:)
It would be nice to have a bit of coordination there perhaps. For now I think other libraries are copying the parts they need, which is fine I guess - but I'd rather not see functionality with poor APIs or questionable algorithms copied (looking at you,
I expect there to be some follow-up yes within the next months. We basically have all the pieces of the puzzle to start connecting things together - see, e.g., scipy/scipy#10204 for how to connect
My feeling is that scikit-learn is in a much better place, because it has done an exceptional job with careful API design and creating compatible APIs in other packages can be and is being done. Maybe @amueller can say more about this. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the information -- what will be the right place to track the follow-ups on accelerating SciPy? FYI, I will spend my time experimenting with |
Beta Was this translation helpful? Give feedback.
-
FYI, PyTorch 1.9 (released today) reimplements |
Beta Was this translation helpful? Give feedback.
-
The
That sounds cool. For that topic I'd suggest opening a tracking issue on the SciPy repo. |
Beta Was this translation helpful? Give feedback.
-
This issue is meant to summarize the current status and likely future direction of the NumPy array protocols, and their relevance to the array API standard.
What are these array protocols?
In summary, they are dispatching mechanisms that allow calling the public NumPy API with other
numpy.ndarray
-like arrays (e.g. CuPy or Dask arrays, or any other array that implements the protocols) and have the function call dispatch to that library. There are two protocols,__array_ufunc__
and__array_function__
, that are very similar - the difference is that with__array_ufunc__
the library being dispatched to knows it's getting a ufunc and it can therefore make use of some properties all ufuncs have. The dispatching works the same for both protocols though.Why were they created?
__array_ufunc__
was created first, the original driver was to be able to call numpy ufuncs onscipy.sparse
matrices.__array_function__
was created later, to be able to cover most of the NumPy API (every function that takes an array as input) and use the NumPy API with other array/tensor implementations:What is the current status?
The protocols have been adopted by:
They have not (or not yet) been adopted by:
scipy.sparse
(semantics not compatible)The RAPIDS ecosystem, which builds on Dask and CuPy, has been particularly happy with these protocols, and use them heavily. There they've also run into some of the limitations, the most painful one being that array creation functions cannot be dispatched on.
What is likely to change in the near future?
There is still active exploration of new ideas and design alternatives (or additions to) the array protocols. There's 3 main "contenders":
__duckarray__
) + NEP 35 (like=
).__array_module__
)unumpy
)At the moment, the most likely outcome is doing both (1) and (2). It needs prototyping and testing though - any solution should only be accepted when it's clear that it not only solves the immediate pain points RAPIDS ran into, but also that libraries like scikit-learn and SciPy can then adopt it.
What is the relationship of the array protocols with an API standard?
There's several connections:
__array_function__
(figure above) doesn't require an API that's the same as the NumPy one, but in practice the protocols can only be adopted when there's an API with matching signatures and semantics.__array_module__
,unumpy
) provide a good opportunity to introduce a new API standard once that's agreed on.References
__array_function__
Beta Was this translation helpful? Give feedback.
All reactions