Skip to content

Commit d557948

Browse files
committed
Write some dev docs, and various other improvements to the documentation
1 parent 3ae70f6 commit d557948

File tree

3 files changed

+129
-18
lines changed

3 files changed

+129
-18
lines changed

docs/dev/implementation-notes.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,77 @@
11
# Implementation Notes
22

3+
This page outlines some notes on the implementation of array-api-compat. These
4+
details are not important for users of the package, but they may be useful to
5+
contributors.
6+
7+
## Special Considerations
8+
9+
array-api-compat requires some special development considerations that are
10+
different from most other Python libraries. The goal of array-api-compat is to
11+
be a small library that packages can either vendor or add as a dependency to
12+
implement array API support. Consequently, certain design considerations
13+
should be taken into account:
14+
15+
- *No Hard Dependencies.* Although array-api-compat "depends" on NumPy, CuPy,
16+
PyTorch, etc., it does not hard depend on them. These libraries are not
17+
imported unless either an array object is passed to `array_namespace()`, or
18+
the specific `array_api_compat.<namespace>` sub-namespace is explicitly
19+
imported.
20+
21+
- *Vendorability.* array-api-compat should be [vendorable](vendoring). This
22+
means that, for instance, all imports in the library are relative imports.
23+
No code in the package specifically references the name `array_api_compat`
24+
(we also support renaming the package to something else).
25+
Vendorability support is tested in `tests/test_vendoring.py`.
26+
27+
- *Pure Python.* To make array-api-compat as easy as possible to add as a
28+
dependency, the code is all pure Python.
29+
30+
- *Minimal Wrapping Only.* The wrapping functionality is minimal. This means
31+
that if something is difficult to wrap using pure Python, or if trying to
32+
support some array API behavior would require a significant amount of code,
33+
we prefer to leave the behavior as an upstream issue for the array library,
34+
and [document it as a known difference](../supported-array-libraries.md).
35+
36+
This also means that we do not at this point in time implement anything
37+
other than wrappers for functions in the standard, and basic [helper
38+
functions](../helper-functions.md) that would be useful for most users of
39+
array-api-compat. The addition of functions that are not part of the array
40+
API standard is currently out-of-scope for this package.
41+
42+
- *No Monkey Patching.* `array-api-compat` should not attempt to modify anything
43+
about the underlying library. It is a *wrapper* library only.
44+
45+
- *No modifying the array object.* Due to the above restrictions, the array
46+
(or tensor) object of the array library cannot be modified. Any behavior
47+
that is built-in to the array object, such as the behavior of [array
48+
methods](https://data-apis.org/array-api/latest/API_specification/array_object.html)
49+
is therefore left unwrapped. Users can workaround issues by using
50+
corresponding [elementwise
51+
functions](https://data-apis.org/array-api/latest/API_specification/elementwise_functions.html)
52+
instead of operators, and using the [helper
53+
functions](../helper-functions.md) provided by array-api-compat instead of
54+
methods like `to_device`.
55+
56+
- *Avoid Restricting Non-Standard Behavior.* All array libraries have
57+
functions and behaviors that are outside of the scope of what is specified
58+
by the standard. These behaviors should be left intact whenever possible,
59+
unless the standard explicitly disallows something. This means
60+
61+
- All namespaces are *extended* with wrapper functions. You may notice the
62+
extensive use of `import *` in various files in `array_api_compat`. While
63+
this would normally be questionable, this is the [one actual legitimate
64+
use-case for `import *`](https://peps.python.org/pep-0008/#imports), to
65+
re-export names from an external namespace.
66+
67+
- All wrapper functions pass `**kwargs` through to the wrapped function.
68+
69+
The onus is on users of array-api-compat to ensure they are only using
70+
portable array API behavior, e.g., by testing against [array-api-strict](array-api-strict).
71+
72+
73+
## Avoiding Code Duplication
74+
375
As noted before, the goal of this library is to reuse the NumPy and CuPy array
476
objects, rather than wrapping or extending them. This means that the functions
577
need to accept and return `np.ndarray` for NumPy and `cp.ndarray` for CuPy.
@@ -64,3 +136,25 @@ corresponding document does not yet exist for PyTorch, but you can examine the
64136
various comments in the
65137
[implementation](https://github.com/data-apis/array-api-compat/blob/main/array_api_compat/torch/_aliases.py)
66138
to see what functions and behaviors have been wrapped.
139+
140+
## Tests
141+
142+
The majority of the behavior for array-api-compat is tested by the
143+
[array-api-tests](https://github.com/data-apis/array-api-tests) test suite for
144+
the array API standard. There are also specific tests in
145+
[`tests/`](https://github.com/data-apis/array-api-compat/tree/main/tests).
146+
These tests should be limited to things that are not tested by the test suite,
147+
e.g., tests for [helper functions](../helper-functions.md) or for behavior that is
148+
not strictly required by the standard.
149+
150+
array-api-tests is run against all supported libraries are tested on CI
151+
(except for JAX,
152+
[wrapping](jax-support)). This is achieved by a [reusable GitHub Actions
153+
Workflow](https://github.com/data-apis/array-api-compat/blob/main/.github/workflows/array-api-tests.yml).
154+
Most libraries have tests that must be xfailed or skipped for various reasons.
155+
These are defined in specific `<library>-xfails.txt` files and are
156+
automatically forwarded to array-api-tests.
157+
158+
Array libraries that require a GPU to run (currently only CuPy) cannot be
159+
tested on CI. There is a helper script `test_cupy.sh` that can be used to
160+
manually test CuPy on a machine with a CUDA GPU.

docs/index.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,16 @@ namespace, except that functions that are part of the array API are wrapped so
7171
that they have the correct array API behavior. In each case, the array object
7272
used will be the same array object from the wrapped library.
7373

74+
(array-api-strict)=
7475
## Difference between `array_api_compat` and `array_api_strict`
7576

76-
`array_api_strict` is a strict minimal implementation of the array API standard, formerly
77-
known as `numpy.array_api` (see
78-
[NEP 47](https://numpy.org/neps/nep-0047-array-api-standard.html)). For
79-
example, `array_api_strict` does not include any functions that are not part of
80-
the array API specification, and will explicitly disallow behaviors that are
81-
not required by the spec (e.g., [cross-kind type
77+
[`array_api_strict`](https://github.com/data-apis/array-api-strict) is a
78+
strict minimal implementation of the array API standard, formerly known as
79+
`numpy.array_api` (see [NEP
80+
47](https://numpy.org/neps/nep-0047-array-api-standard.html)). For example,
81+
`array_api_strict` does not include any functions that are not part of the
82+
array API specification, and will explicitly disallow behaviors that are not
83+
required by the spec (e.g., [cross-kind type
8284
promotions](https://data-apis.org/array-api/latest/API_specification/type_promotion.html)).
8385
(`cupy.array_api` is similar to `array_api_strict`)
8486

@@ -101,6 +103,7 @@ against `array_api_strict` to ensure they are not using functionality outside
101103
of the standard, but prefer this implementation for the default behavior for
102104
end-users.
103105

106+
(vendoring)=
104107
## Vendoring
105108

106109
This library supports vendoring as an installation method. To vendor the
@@ -122,6 +125,6 @@ Alternatively, the library may be installed as dependency on PyPI.
122125
:hidden:
123126
124127
helper-functions.md
125-
differences.md
128+
supported-array-libraries.md
126129
dev/index.md
127130
```

docs/differences.md renamed to docs/supported-array-libraries.md

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
1-
# Differences from the Array API Specification
1+
# Supported Array Libraries
22

3-
There are some known differences between this library and the array API
4-
specification:
3+
The following array libraries are supported. This page outlines the known
4+
differences between this library and the array API specification for the
5+
supported packages.
56

6-
## NumPy and CuPy
7+
Note that the [`array_namespace()`](helper-functions.md) helper will also
8+
support any array library that explicitly supports the array API by defining
9+
[`__array_namespace__`](https://data-apis.org/array-api/latest/API_specification/generated/array_api.array.__array_namespace__.html).
10+
11+
## [NumPy](https://numpy.org/) and [CuPy](https://cupy.dev/)
12+
13+
NumPy 2.0 has full array API compatibility. This package is not strictly
14+
necessary for NumPy 2.0 support, but may still be useful for the support of
15+
other libraries, as well as for the [helper functions](helper-functions.md).
16+
17+
For NumPy 1.26, as well as corresponding versions of CuPy, the following
18+
deviations from the standard should be noted:
719

820
- The array methods `__array_namespace__`, `device` (for NumPy), `to_device`,
921
and `mT` are not defined. This reuses `np.ndarray` and `cp.ndarray` and we
10-
don't want to monkeypatch or wrap it. The helper functions `device()` and
11-
`to_device()` are provided to work around these missing methods (see above).
12-
`x.mT` can be replaced with `xp.linalg.matrix_transpose(x)`.
13-
`array_namespace(x)` should be used instead of `x.__array_namespace__`.
22+
don't want to monkey patch or wrap it. The [helper
23+
functions](helper-functions.md) `device()` and `to_device()` are provided to
24+
work around these missing methods. `x.mT` can be replaced with
25+
`xp.linalg.matrix_transpose(x)`. `array_namespace(x)` should be used instead
26+
of `x.__array_namespace__`.
1427

1528
- Value-based casting for scalars will be in effect unless explicitly disabled
1629
with the environment variable `NPY_PROMOTION_STATE=weak` or
@@ -41,7 +54,7 @@ NumPy has a few issues:
4154
If any of these are an issue, it is recommended to bump your minimum NumPy
4255
version.
4356

44-
## PyTorch
57+
## [PyTorch](https://pytorch.org/)
4558

4659
- Like NumPy/CuPy, we do not wrap the `torch.Tensor` object. It is missing the
4760
`__array_namespace__` and `to_device` methods, so the corresponding helper
@@ -85,13 +98,14 @@ version.
8598

8699
The minimum supported PyTorch version is 1.13.
87100

88-
## JAX
101+
(jax-support)=
102+
## [JAX](https://jax.readthedocs.io/en/latest/)
89103

90104
Unlike the other libraries supported here, JAX array API support is contained
91105
entirely in the JAX library. The JAX array API support is tracked at
92106
https://github.com/google/jax/issues/18353.
93107

94-
## Dask
108+
## [Dask](https://www.dask.org/)
95109

96110
If you're using dask with numpy, many of the same limitations that apply to numpy
97111
will also apply to dask. Besides those differences, other limitations include missing

0 commit comments

Comments
 (0)