-
Notifications
You must be signed in to change notification settings - Fork 11
Implement CupyArrayContext #251
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
base: main
Are you sure you want to change the base?
Changes from all commits
7ab5211
96b7a3d
8dee38d
2c025eb
d6e3136
bfa648a
27e5a19
6d507e1
8fb4e0b
be70b67
677419b
6250211
d61f0cf
5871ae7
9c56443
fd95813
5f4c4d9
a8fe272
2296c6d
8fd5488
6f3cd94
ab8266d
79b0bc3
70aff99
8b5c6cf
8561b2f
904e061
340f9dc
3ee28cc
ce33f23
cd2a366
8e7e1f1
326e164
4d429f8
69e2133
f83ee9c
fae85a4
d9ce8d5
1f5649c
f16bc29
ebd4828
dc62cdc
22649a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,9 @@ jobs: | |
curl -L -O https://tiker.net/ci-support-v0 | ||
. ./ci-support-v0 | ||
|
||
CONDA_ENVIRONMENT=.test-conda-env-py3.yml | ||
echo "- cupy" >> "$CONDA_ENVIRONMENT" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you adapt There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 79b0bc3 et al., and seems to work: https://gitlab.tiker.net/inducer/arraycontext/-/jobs/804938 |
||
|
||
build_py_project_in_conda_env | ||
cipip install basedpyright | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,8 @@ GPU arrays? Deferred-evaluation arrays? Just plain ``numpy`` arrays? You'd like | |
code to work with all of them? No problem! Comes with pre-made array context | ||
implementations for: | ||
|
||
- numpy | ||
- `numpy <https://numpy.org>`__ | ||
- `cupy <https://cupy.dev>`__ | ||
- `PyOpenCL <https://documen.tician.de/pyopencl/array.html>`__ | ||
- `JAX <https://jax.readthedocs.io/en/latest/>`__ | ||
- `Pytato <https://documen.tician.de/pytato>`__ (for lazy/deferred evaluation) | ||
|
@@ -24,7 +25,7 @@ implementations for: | |
- Profiling | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, what are the implementations for debugging/profiling? (also mentioned in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think there are any at the moment (?). Unless passing a It would be nice to have some fancier profiling for things though 😁 |
||
|
||
``arraycontext`` started life as an array abstraction for use with the | ||
`meshmode <https://documen.tician.de/meshmode/>`__ unstrucuted discretization | ||
`meshmode <https://documen.tician.de/meshmode/>`__ unstructured discretization | ||
package. | ||
|
||
Distributed under the MIT license. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
""" | ||
.. currentmodule:: arraycontext | ||
|
||
A :mod:`cupy`-based array context. | ||
|
||
.. autoclass:: CupyArrayContext | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
|
||
__copyright__ = """ | ||
Copyright (C) 2024 University of Illinois Board of Trustees | ||
""" | ||
|
||
__license__ = """ | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
""" | ||
|
||
from typing import Any, overload | ||
|
||
import numpy as np | ||
|
||
import loopy as lp | ||
from pytools.tag import ToTagSetConvertible | ||
|
||
from arraycontext.container.traversal import rec_map_array_container, with_array_context | ||
from arraycontext.context import ( | ||
Array, | ||
ArrayContext, | ||
ArrayOrContainerOrScalar, | ||
ArrayOrContainerOrScalarT, | ||
ContainerOrScalarT, | ||
NumpyOrContainerOrScalar, | ||
) | ||
|
||
|
||
class CupyNonObjectArrayMetaclass(type): | ||
def __instancecheck__(cls, instance: Any) -> bool: | ||
import cupy as cp # type: ignore[import-untyped] | ||
return isinstance(instance, cp.ndarray) and instance.dtype != object | ||
|
||
|
||
class CupyNonObjectArray(metaclass=CupyNonObjectArrayMetaclass): | ||
pass | ||
|
||
|
||
class CupyArrayContext(ArrayContext): | ||
"""An :class:`ArrayContext` that uses :class:`cupy.ndarray` to represent arrays.""" | ||
|
||
array_types = (CupyNonObjectArray,) | ||
alexfikl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def _get_fake_numpy_namespace(self): | ||
from .fake_numpy import CupyFakeNumpyNamespace | ||
return CupyFakeNumpyNamespace(self) | ||
|
||
# {{{ ArrayContext interface | ||
|
||
def clone(self): | ||
return type(self)() | ||
matthiasdiener marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
@overload | ||
def from_numpy(self, array: np.ndarray[Any, Any]) -> Array: | ||
... | ||
|
||
@overload | ||
def from_numpy(self, array: ContainerOrScalarT) -> ContainerOrScalarT: | ||
... | ||
|
||
def from_numpy(self, | ||
array: NumpyOrContainerOrScalar | ||
) -> ArrayOrContainerOrScalar: | ||
import cupy as cp | ||
return with_array_context(rec_map_array_container(cp.array, array), | ||
actx=self) | ||
|
||
@overload | ||
def to_numpy(self, array: Array) -> np.ndarray[Any, Any]: | ||
... | ||
|
||
@overload | ||
def to_numpy(self, array: ContainerOrScalarT) -> ContainerOrScalarT: | ||
... | ||
|
||
def to_numpy(self, | ||
array: ArrayOrContainerOrScalar | ||
) -> NumpyOrContainerOrScalar: | ||
import cupy as cp | ||
return with_array_context(rec_map_array_container(cp.asnumpy, array), | ||
actx=None) | ||
|
||
def call_loopy( | ||
self, | ||
t_unit: lp.TranslationUnit, **kwargs: Any | ||
) -> dict[str, Array]: | ||
raise NotImplementedError( | ||
"Calling loopy on CuPy arrays is not supported. Maybe rewrite" | ||
" the loopy kernel as numpy-flavored array operations using" | ||
" ArrayContext.np.") | ||
|
||
def freeze(self, array): | ||
import cupy as cp | ||
# Note that we could use a non-blocking version of cp.asnumpy here, but | ||
# it appears to have very little impact on performance. | ||
return with_array_context(rec_map_array_container(cp.asnumpy, array), actx=None) | ||
|
||
def thaw(self, array): | ||
import cupy as cp | ||
return with_array_context(rec_map_array_container(cp.array, array), actx=self) | ||
|
||
# }}} | ||
|
||
def tag(self, | ||
tags: ToTagSetConvertible, | ||
array: ArrayOrContainerOrScalarT) -> ArrayOrContainerOrScalarT: | ||
# Cupy (like numpy) doesn't support tagging | ||
return array | ||
|
||
def tag_axis(self, | ||
iaxis: int, tags: ToTagSetConvertible, | ||
array: ArrayOrContainerOrScalarT) -> ArrayOrContainerOrScalarT: | ||
# Cupy (like numpy) doesn't support tagging | ||
return array | ||
|
||
def einsum(self, spec, *args, arg_names=None, tagged=()): | ||
import cupy as cp | ||
return cp.einsum(spec, *args) | ||
|
||
@property | ||
def permits_inplace_modification(self): | ||
return True | ||
|
||
@property | ||
def supports_nonscalar_broadcasting(self): | ||
return True | ||
|
||
@property | ||
def permits_advanced_indexing(self): | ||
return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that CI for this is not running on Github (and cannot run). Why install the package then? (Also above.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If cupy is not installed, these tests will fail, e.g. mypy with
arraycontext/impl/cupy/__init__.py:57: error: Cannot find implementation or library stub for module named "cupy" [import-not-found]
. We couldtype: ignore
these, but at least in the case of pylint we would have to annotate everyimport cupy
line with# pylint: disable=import-error
. Not sure which way is better.