cunumpy 0.6.3__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cunumpy-0.6.3/src/cunumpy.egg-info → cunumpy-0.7.0}/PKG-INFO +35 -41
- {cunumpy-0.6.3 → cunumpy-0.7.0}/README.md +30 -30
- {cunumpy-0.6.3 → cunumpy-0.7.0}/pyproject.toml +5 -13
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/LLM_GUIDE.md +2 -2
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/__init__.py +1 -1
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_cuda_kernel.py +4 -3
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_device.py +4 -3
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_dispatch.py +4 -3
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_fake_cupyx.py +10 -8
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_kernel.py +95 -14
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_morton.py +1 -1
- cunumpy-0.7.0/src/cunumpy/_pyccel_cache.py +305 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_random_streams.py +2 -2
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_scipy_backend.py +7 -5
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_transfers.py +1 -1
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/kernel_testing.py +6 -4
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/kernels.py +11 -2
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/xp.py +9 -7
- {cunumpy-0.6.3 → cunumpy-0.7.0/src/cunumpy.egg-info}/PKG-INFO +35 -41
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy.egg-info/SOURCES.txt +1 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy.egg-info/requires.txt +4 -10
- {cunumpy-0.6.3 → cunumpy-0.7.0}/LICENSE.txt +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/setup.cfg +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/__init__.pyi +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_algorithms.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_emulation.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_fake_cupy.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_fake_cupy_impl.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_fusion.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_host.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_linalg.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_metal_kernel.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_mirror.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_mpi.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_optimize.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_philox.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_profiling.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_scipy_host.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_staging.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/_streams.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/algorithms.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/arguments.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/cuda/__init__.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/cuda/include/cunumpy/array_view.cuh +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/cuda/include/cunumpy/atomic.cuh +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/cuda/include/cunumpy/index.cuh +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/cuda/include/cunumpy/morton.cuh +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/cuda/include/cunumpy/random.cuh +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/cuda/include/cunumpy/reduce.cuh +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/cuda/include/cunumpy/scan.cuh +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/integrate.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/memory.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/mpi.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/optimize.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/petsc.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/profiling.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/py.typed +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy/rng.py +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy.egg-info/dependency_links.txt +0 -0
- {cunumpy-0.6.3 → cunumpy-0.7.0}/src/cunumpy.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cunumpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Simple wrapper for numpy and cupy. Replace `import numpy as np` with `import cunumpy as xp`.
|
|
5
5
|
Author: Max
|
|
6
6
|
License: MIT License
|
|
@@ -41,19 +41,13 @@ Requires-Dist: array-api-compat
|
|
|
41
41
|
Requires-Dist: maybempi>=0.1.2
|
|
42
42
|
Requires-Dist: numpy
|
|
43
43
|
Provides-Extra: dev
|
|
44
|
-
Requires-Dist: ruff; extra == "dev"
|
|
45
44
|
Requires-Dist: cunumpy[docs,test-compiled]; extra == "dev"
|
|
45
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
46
|
+
Requires-Dist: pyproject-fmt; extra == "dev"
|
|
47
|
+
Requires-Dist: ruff; extra == "dev"
|
|
46
48
|
Provides-Extra: docs
|
|
49
|
+
Requires-Dist: griffe; extra == "docs"
|
|
47
50
|
Requires-Dist: ipykernel; extra == "docs"
|
|
48
|
-
Requires-Dist: myst-parser; extra == "docs"
|
|
49
|
-
Requires-Dist: nbconvert; extra == "docs"
|
|
50
|
-
Requires-Dist: nbsphinx; extra == "docs"
|
|
51
|
-
Requires-Dist: numpydoc; extra == "docs"
|
|
52
|
-
Requires-Dist: jupyterlab; extra == "docs"
|
|
53
|
-
Requires-Dist: pre-commit; extra == "docs"
|
|
54
|
-
Requires-Dist: pyproject-fmt; extra == "docs"
|
|
55
|
-
Requires-Dist: sphinx; extra == "docs"
|
|
56
|
-
Requires-Dist: sphinx-book-theme; extra == "docs"
|
|
57
51
|
Provides-Extra: metal
|
|
58
52
|
Requires-Dist: mlx; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "metal"
|
|
59
53
|
Provides-Extra: test
|
|
@@ -104,7 +98,7 @@ never hide a NumPy name:
|
|
|
104
98
|
|
|
105
99
|
Everything except `xp.cuda`, `xp.arguments` and `CudaKernel` works on both backends.
|
|
106
100
|
`MetalKernel` runs Metal kernels on the GPU of an Apple silicon Mac (MLX, float32, NumPy arrays;
|
|
107
|
-
`pip install 'cunumpy[metal]'`, see [the guide](
|
|
101
|
+
`pip install 'cunumpy[metal]'`, see [the guide](https://max-models.github.io/cunumpy/kernels/metal-kernel/)).
|
|
108
102
|
|
|
109
103
|
## Install
|
|
110
104
|
|
|
@@ -120,7 +114,7 @@ installation instructions for your system. CuNumpy does not install CUDA.
|
|
|
120
114
|
`array-api-compat` supplies NumPy and CuPy compatibility modules with more
|
|
121
115
|
consistent behavior for shared array operations. CuNumpy uses them internally;
|
|
122
116
|
your arrays remain ordinary NumPy or CuPy arrays. See [why CuNumpy uses
|
|
123
|
-
`array-api-compat`](
|
|
117
|
+
`array-api-compat`](https://max-models.github.io/cunumpy/guides/array-api-compat/) for a plain-language
|
|
124
118
|
explanation and examples.
|
|
125
119
|
|
|
126
120
|
## Choose a backend
|
|
@@ -146,7 +140,7 @@ Use `xp.set_backend("cupy", strict=True)` to raise when CUDA is unavailable,
|
|
|
146
140
|
preserving the previous backend. `xp.backend_info()` returns structured backend,
|
|
147
141
|
dependency, and CUDA diagnostics. Reusable streams/events, MPI staging, cell
|
|
148
142
|
ranges, and prepared reductions are described in the
|
|
149
|
-
[execution helpers guide](
|
|
143
|
+
[execution helpers guide](https://max-models.github.io/cunumpy/guides/execution-helpers/).
|
|
150
144
|
|
|
151
145
|
Use `use_backend()` for a temporary selection. It restores the previous
|
|
152
146
|
selection when the block exits, including when an exception is raised:
|
|
@@ -367,7 +361,7 @@ read-only inputs. For a keyword call, declare the keyword name, such as
|
|
|
367
361
|
`outputs=("out",)`. A wrong declaration can leave GPU output values stale.
|
|
368
362
|
The wrapper can also traverse arrays nested in lists, tuples, dictionaries,
|
|
369
363
|
and selected application objects; see [Host kernels with GPU
|
|
370
|
-
data](
|
|
364
|
+
data](https://max-models.github.io/cunumpy/kernels/pyccel-kernel/) for `object_modules`, `is_array`,
|
|
371
365
|
aliasing, and output declarations.
|
|
372
366
|
|
|
373
367
|
## Write CUDA kernels next to host kernels
|
|
@@ -504,8 +498,8 @@ an explicit `grid`, with dynamic shared memory (`shared_mem`) and a `stream`.
|
|
|
504
498
|
C++ function templates are instantiated with `template_args`, and
|
|
505
499
|
`CudaKernelVariants` caches kernels whose source is generated per variant
|
|
506
500
|
(e.g. per dimension and dtype). See [Writing CUDA
|
|
507
|
-
kernels](
|
|
508
|
-
headers](
|
|
501
|
+
kernels](https://max-models.github.io/cunumpy/kernels/cuda-kernel/) and [CUDA
|
|
502
|
+
headers](https://max-models.github.io/cunumpy/kernels/cuda-headers/) for details.
|
|
509
503
|
|
|
510
504
|
Kernels run asynchronously, so a CUDA error (an illegal memory access, say)
|
|
511
505
|
normally surfaces at a later `.get()` or MPI call, far from the kernel that
|
|
@@ -565,36 +559,36 @@ mirror.to_host() # vector._data holds the result on both backends
|
|
|
565
559
|
|
|
566
560
|
CuNumpy supports the NumPy backend in Pyodide. It does not provide CuPy/CUDA
|
|
567
561
|
there. Ordinary Python callables can be wrapped with `PyccelKernel` without
|
|
568
|
-
compilation. See the [Pyodide guide](
|
|
562
|
+
compilation. See the [Pyodide guide](https://max-models.github.io/cunumpy/pyodide/) for a complete
|
|
569
563
|
installation example and compatibility notes.
|
|
570
564
|
|
|
571
565
|
## Documentation
|
|
572
566
|
|
|
573
|
-
The full documentation lives in [`docs
|
|
567
|
+
The full documentation lives in [`docs/`](docs/) (Astro + Starlight, `make docs-build`) and is
|
|
574
568
|
published at <https://max-models.github.io/cunumpy/>:
|
|
575
569
|
|
|
576
|
-
* Getting started: [installation](
|
|
577
|
-
[quickstart](
|
|
578
|
-
* User guide: [choosing a backend](
|
|
579
|
-
[backend-agnostic code](
|
|
580
|
-
[data movement](
|
|
581
|
-
[devices, memory and streams](
|
|
582
|
-
[MPI with one rank per GPU](
|
|
583
|
-
[timing and profiling](
|
|
584
|
-
* Porting kernels: [overview](
|
|
585
|
-
[`PyccelKernel`](
|
|
586
|
-
[`CudaKernel`](
|
|
587
|
-
[`Kernel` and `KernelCatalog`](
|
|
588
|
-
[argument objects and structs](
|
|
589
|
-
[accumulation kernels](
|
|
590
|
-
[debugging](
|
|
591
|
-
[testing](
|
|
592
|
-
* [Worked examples](
|
|
593
|
-
[best practices](
|
|
594
|
-
[troubleshooting](
|
|
595
|
-
[Pyodide](
|
|
596
|
-
[API overview](
|
|
597
|
-
[API reference](
|
|
570
|
+
* Getting started: [installation](https://max-models.github.io/cunumpy/getting-started/installation/) and a
|
|
571
|
+
[quickstart](https://max-models.github.io/cunumpy/getting-started/quickstart/) with a map of which guide covers what.
|
|
572
|
+
* User guide: [choosing a backend](https://max-models.github.io/cunumpy/guides/backends/),
|
|
573
|
+
[backend-agnostic code](https://max-models.github.io/cunumpy/guides/portable-code/),
|
|
574
|
+
[data movement](https://max-models.github.io/cunumpy/guides/data-movement/),
|
|
575
|
+
[devices, memory and streams](https://max-models.github.io/cunumpy/guides/gpu-devices/),
|
|
576
|
+
[MPI with one rank per GPU](https://max-models.github.io/cunumpy/guides/mpi/),
|
|
577
|
+
[timing and profiling](https://max-models.github.io/cunumpy/guides/profiling/).
|
|
578
|
+
* Porting kernels: [overview](https://max-models.github.io/cunumpy/kernels/overview/),
|
|
579
|
+
[`PyccelKernel`](https://max-models.github.io/cunumpy/kernels/pyccel-kernel/),
|
|
580
|
+
[`CudaKernel`](https://max-models.github.io/cunumpy/kernels/cuda-kernel/),
|
|
581
|
+
[`Kernel` and `KernelCatalog`](https://max-models.github.io/cunumpy/kernels/dispatch/),
|
|
582
|
+
[argument objects and structs](https://max-models.github.io/cunumpy/kernels/arguments/),
|
|
583
|
+
[accumulation kernels](https://max-models.github.io/cunumpy/kernels/accumulation/),
|
|
584
|
+
[debugging](https://max-models.github.io/cunumpy/kernels/debugging/),
|
|
585
|
+
[testing](https://max-models.github.io/cunumpy/kernels/testing/).
|
|
586
|
+
* [Worked examples](https://max-models.github.io/cunumpy/examples/),
|
|
587
|
+
[best practices](https://max-models.github.io/cunumpy/best-practices/),
|
|
588
|
+
[troubleshooting](https://max-models.github.io/cunumpy/troubleshooting/),
|
|
589
|
+
[Pyodide](https://max-models.github.io/cunumpy/pyodide/), the
|
|
590
|
+
[API overview](https://max-models.github.io/cunumpy/reference/overview/) and the
|
|
591
|
+
[API reference](https://max-models.github.io/cunumpy/reference/).
|
|
598
592
|
|
|
599
593
|
### For AI coding assistants
|
|
600
594
|
|
|
@@ -37,7 +37,7 @@ never hide a NumPy name:
|
|
|
37
37
|
|
|
38
38
|
Everything except `xp.cuda`, `xp.arguments` and `CudaKernel` works on both backends.
|
|
39
39
|
`MetalKernel` runs Metal kernels on the GPU of an Apple silicon Mac (MLX, float32, NumPy arrays;
|
|
40
|
-
`pip install 'cunumpy[metal]'`, see [the guide](
|
|
40
|
+
`pip install 'cunumpy[metal]'`, see [the guide](https://max-models.github.io/cunumpy/kernels/metal-kernel/)).
|
|
41
41
|
|
|
42
42
|
## Install
|
|
43
43
|
|
|
@@ -53,7 +53,7 @@ installation instructions for your system. CuNumpy does not install CUDA.
|
|
|
53
53
|
`array-api-compat` supplies NumPy and CuPy compatibility modules with more
|
|
54
54
|
consistent behavior for shared array operations. CuNumpy uses them internally;
|
|
55
55
|
your arrays remain ordinary NumPy or CuPy arrays. See [why CuNumpy uses
|
|
56
|
-
`array-api-compat`](
|
|
56
|
+
`array-api-compat`](https://max-models.github.io/cunumpy/guides/array-api-compat/) for a plain-language
|
|
57
57
|
explanation and examples.
|
|
58
58
|
|
|
59
59
|
## Choose a backend
|
|
@@ -79,7 +79,7 @@ Use `xp.set_backend("cupy", strict=True)` to raise when CUDA is unavailable,
|
|
|
79
79
|
preserving the previous backend. `xp.backend_info()` returns structured backend,
|
|
80
80
|
dependency, and CUDA diagnostics. Reusable streams/events, MPI staging, cell
|
|
81
81
|
ranges, and prepared reductions are described in the
|
|
82
|
-
[execution helpers guide](
|
|
82
|
+
[execution helpers guide](https://max-models.github.io/cunumpy/guides/execution-helpers/).
|
|
83
83
|
|
|
84
84
|
Use `use_backend()` for a temporary selection. It restores the previous
|
|
85
85
|
selection when the block exits, including when an exception is raised:
|
|
@@ -300,7 +300,7 @@ read-only inputs. For a keyword call, declare the keyword name, such as
|
|
|
300
300
|
`outputs=("out",)`. A wrong declaration can leave GPU output values stale.
|
|
301
301
|
The wrapper can also traverse arrays nested in lists, tuples, dictionaries,
|
|
302
302
|
and selected application objects; see [Host kernels with GPU
|
|
303
|
-
data](
|
|
303
|
+
data](https://max-models.github.io/cunumpy/kernels/pyccel-kernel/) for `object_modules`, `is_array`,
|
|
304
304
|
aliasing, and output declarations.
|
|
305
305
|
|
|
306
306
|
## Write CUDA kernels next to host kernels
|
|
@@ -437,8 +437,8 @@ an explicit `grid`, with dynamic shared memory (`shared_mem`) and a `stream`.
|
|
|
437
437
|
C++ function templates are instantiated with `template_args`, and
|
|
438
438
|
`CudaKernelVariants` caches kernels whose source is generated per variant
|
|
439
439
|
(e.g. per dimension and dtype). See [Writing CUDA
|
|
440
|
-
kernels](
|
|
441
|
-
headers](
|
|
440
|
+
kernels](https://max-models.github.io/cunumpy/kernels/cuda-kernel/) and [CUDA
|
|
441
|
+
headers](https://max-models.github.io/cunumpy/kernels/cuda-headers/) for details.
|
|
442
442
|
|
|
443
443
|
Kernels run asynchronously, so a CUDA error (an illegal memory access, say)
|
|
444
444
|
normally surfaces at a later `.get()` or MPI call, far from the kernel that
|
|
@@ -498,36 +498,36 @@ mirror.to_host() # vector._data holds the result on both backends
|
|
|
498
498
|
|
|
499
499
|
CuNumpy supports the NumPy backend in Pyodide. It does not provide CuPy/CUDA
|
|
500
500
|
there. Ordinary Python callables can be wrapped with `PyccelKernel` without
|
|
501
|
-
compilation. See the [Pyodide guide](
|
|
501
|
+
compilation. See the [Pyodide guide](https://max-models.github.io/cunumpy/pyodide/) for a complete
|
|
502
502
|
installation example and compatibility notes.
|
|
503
503
|
|
|
504
504
|
## Documentation
|
|
505
505
|
|
|
506
|
-
The full documentation lives in [`docs
|
|
506
|
+
The full documentation lives in [`docs/`](docs/) (Astro + Starlight, `make docs-build`) and is
|
|
507
507
|
published at <https://max-models.github.io/cunumpy/>:
|
|
508
508
|
|
|
509
|
-
* Getting started: [installation](
|
|
510
|
-
[quickstart](
|
|
511
|
-
* User guide: [choosing a backend](
|
|
512
|
-
[backend-agnostic code](
|
|
513
|
-
[data movement](
|
|
514
|
-
[devices, memory and streams](
|
|
515
|
-
[MPI with one rank per GPU](
|
|
516
|
-
[timing and profiling](
|
|
517
|
-
* Porting kernels: [overview](
|
|
518
|
-
[`PyccelKernel`](
|
|
519
|
-
[`CudaKernel`](
|
|
520
|
-
[`Kernel` and `KernelCatalog`](
|
|
521
|
-
[argument objects and structs](
|
|
522
|
-
[accumulation kernels](
|
|
523
|
-
[debugging](
|
|
524
|
-
[testing](
|
|
525
|
-
* [Worked examples](
|
|
526
|
-
[best practices](
|
|
527
|
-
[troubleshooting](
|
|
528
|
-
[Pyodide](
|
|
529
|
-
[API overview](
|
|
530
|
-
[API reference](
|
|
509
|
+
* Getting started: [installation](https://max-models.github.io/cunumpy/getting-started/installation/) and a
|
|
510
|
+
[quickstart](https://max-models.github.io/cunumpy/getting-started/quickstart/) with a map of which guide covers what.
|
|
511
|
+
* User guide: [choosing a backend](https://max-models.github.io/cunumpy/guides/backends/),
|
|
512
|
+
[backend-agnostic code](https://max-models.github.io/cunumpy/guides/portable-code/),
|
|
513
|
+
[data movement](https://max-models.github.io/cunumpy/guides/data-movement/),
|
|
514
|
+
[devices, memory and streams](https://max-models.github.io/cunumpy/guides/gpu-devices/),
|
|
515
|
+
[MPI with one rank per GPU](https://max-models.github.io/cunumpy/guides/mpi/),
|
|
516
|
+
[timing and profiling](https://max-models.github.io/cunumpy/guides/profiling/).
|
|
517
|
+
* Porting kernels: [overview](https://max-models.github.io/cunumpy/kernels/overview/),
|
|
518
|
+
[`PyccelKernel`](https://max-models.github.io/cunumpy/kernels/pyccel-kernel/),
|
|
519
|
+
[`CudaKernel`](https://max-models.github.io/cunumpy/kernels/cuda-kernel/),
|
|
520
|
+
[`Kernel` and `KernelCatalog`](https://max-models.github.io/cunumpy/kernels/dispatch/),
|
|
521
|
+
[argument objects and structs](https://max-models.github.io/cunumpy/kernels/arguments/),
|
|
522
|
+
[accumulation kernels](https://max-models.github.io/cunumpy/kernels/accumulation/),
|
|
523
|
+
[debugging](https://max-models.github.io/cunumpy/kernels/debugging/),
|
|
524
|
+
[testing](https://max-models.github.io/cunumpy/kernels/testing/).
|
|
525
|
+
* [Worked examples](https://max-models.github.io/cunumpy/examples/),
|
|
526
|
+
[best practices](https://max-models.github.io/cunumpy/best-practices/),
|
|
527
|
+
[troubleshooting](https://max-models.github.io/cunumpy/troubleshooting/),
|
|
528
|
+
[Pyodide](https://max-models.github.io/cunumpy/pyodide/), the
|
|
529
|
+
[API overview](https://max-models.github.io/cunumpy/reference/overview/) and the
|
|
530
|
+
[API reference](https://max-models.github.io/cunumpy/reference/).
|
|
531
531
|
|
|
532
532
|
### For AI coding assistants
|
|
533
533
|
|
|
@@ -5,7 +5,7 @@ requires = [ "setuptools", "wheel" ]
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "cunumpy"
|
|
8
|
-
version = "0.
|
|
8
|
+
version = "0.7.0"
|
|
9
9
|
description = "Simple wrapper for numpy and cupy. Replace `import numpy as np` with `import cunumpy as xp`."
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
keywords = [ "python" ]
|
|
@@ -28,22 +28,14 @@ dependencies = [
|
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
optional-dependencies.dev = [
|
|
31
|
-
"ruff",
|
|
32
31
|
"cunumpy[test-compiled,docs]",
|
|
33
|
-
]
|
|
34
|
-
# https://medium.com/@pratikdomadiya123/build-project-documentation-quickly-with-the-sphinx-python-2a9732b66594
|
|
35
|
-
optional-dependencies.docs = [
|
|
36
|
-
"ipykernel",
|
|
37
|
-
"myst-parser",
|
|
38
|
-
"nbconvert",
|
|
39
|
-
"nbsphinx",
|
|
40
|
-
"numpydoc",
|
|
41
|
-
"jupyterlab",
|
|
42
32
|
"pre-commit",
|
|
43
33
|
"pyproject-fmt",
|
|
44
|
-
"
|
|
45
|
-
"sphinx-book-theme",
|
|
34
|
+
"ruff",
|
|
46
35
|
]
|
|
36
|
+
# the API reference of the docs site (docs/, Astro + Starlight) reads the docstrings with griffe;
|
|
37
|
+
# the shared docs workflow registers an ipykernel even without notebooks
|
|
38
|
+
optional-dependencies.docs = [ "griffe", "ipykernel" ]
|
|
47
39
|
optional-dependencies.metal = [ "mlx; sys_platform == 'darwin' and platform_machine == 'arm64'" ]
|
|
48
40
|
optional-dependencies.test = [ "coverage", "pytest", "scipy" ]
|
|
49
41
|
optional-dependencies.test-compiled = [ "cunumpy[test]", "pyccel" ]
|
|
@@ -5,7 +5,7 @@ correct code with `cunumpy`. It ships inside the installed package
|
|
|
5
5
|
(`<site-packages>/cunumpy/LLM_GUIDE.md`; locate it with
|
|
6
6
|
`python -c "import cunumpy, pathlib; print(pathlib.Path(cunumpy.__file__).parent / 'LLM_GUIDE.md')"`).
|
|
7
7
|
It is self-contained. The full documentation is at
|
|
8
|
-
https://max-models.github.io/cunumpy/ and in `docs
|
|
8
|
+
https://max-models.github.io/cunumpy/ and in `docs/` of the repository.
|
|
9
9
|
|
|
10
10
|
## What cunumpy is
|
|
11
11
|
|
|
@@ -83,7 +83,7 @@ https://max-models.github.io/cunumpy/ and in `docs/source/` of the repository.
|
|
|
83
83
|
| host kernels compiled at first call (your compile function), NumPy fallback | `from_package(..., host_suffix="_pyccel", compile_host=my_compile, host_fallback={...})` -> `xp.kernels.CompiledHostKernel` |
|
|
84
84
|
| host arrays reach kernels while CuPy is active | `Kernel(..., dispatch="arrays")` / `from_package(..., dispatch="arrays")`: CUDA only for device arguments |
|
|
85
85
|
| one kernel folder declares its kernel in its own `__init__.py` | `kernel = xp.kernels.Kernel.from_folder(__name__, host_suffix="_pyccel", compile_host=..., dispatch="arrays")`; `<name>_numba.py`, `<name>_numpy.py` in the folder are further host implementations |
|
|
86
|
-
| bring a `dispatch="arrays"` kernel's arguments to the side of the main array | `xp.kernels.as_kernel_array(a, like=grid, dtype=float)`; outputs: `with xp.kernels.kernel_output(out, like=grid, dtype=float) as buf
|
|
86
|
+
| bring a `dispatch="arrays"` kernel's arguments to the side of the main array | `xp.kernels.as_kernel_array(a, like=grid, dtype=float)`; outputs: `with xp.kernels.kernel_output(out, like=grid, dtype=float) as buf:` (several: `with xp.kernels.kernel_outputs(a, b, like=grid, dtype=float) as (buf_a, buf_b):`); `strided=True` passes NumPy views in C order with gaps (`a[:, :n]`) to Pyccel hosts without a copy |
|
|
87
87
|
| choose the host implementation (pyccel/numba/numpy/python) | `xp.kernels.set_host_kernel_implementation("numpy")`, `with xp.kernels.use_host_kernel_implementation(...)`, `CUNUMPY_HOST_KERNEL_IMPLEMENTATION=numpy`; default: first available of pyccel, numba, numpy; `kernel.selected()` |
|
|
88
88
|
| require CUDA for device kernel dispatch | `xp.kernels.set_device_kernel_implementation("cuda")`, `get_device_kernel_implementation()`, `with xp.kernels.use_device_kernel_implementation(...)`, `CUNUMPY_DEVICE_KERNEL_IMPLEMENTATION=cuda`; default `None` preserves `missing_cuda` policy; explicit CUDA rejects host fallback |
|
|
89
89
|
| check host and CUDA kernels take the same parameters | `catalog.check_signatures()` (in a unit test) |
|
|
@@ -55,8 +55,8 @@ from cunumpy.xp import (
|
|
|
55
55
|
)
|
|
56
56
|
|
|
57
57
|
try:
|
|
58
|
-
#: The installed version of cunumpy; ``"0.0.0+unknown"`` without package metadata.
|
|
59
58
|
__version__ = version("cunumpy")
|
|
59
|
+
"""The installed version of cunumpy; ``"0.0.0+unknown"`` without package metadata."""
|
|
60
60
|
except PackageNotFoundError:
|
|
61
61
|
__version__ = "0.0.0+unknown"
|
|
62
62
|
|
|
@@ -116,10 +116,11 @@ def cuda_include_dir() -> str:
|
|
|
116
116
|
return str(_CUDA_INCLUDE_DIR)
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
#: NVRTC options added in debug mode: line information for
|
|
120
|
-
#: ``compute-sanitizer``/``nsys`` and bounds checks in the array views
|
|
121
|
-
#: (no ``-G``: NVRTC does not support it).
|
|
122
119
|
DEBUG_OPTIONS = ("-lineinfo", "-DCUNUMPY_BOUNDS_CHECK")
|
|
120
|
+
"""NVRTC options added in debug mode: line information for
|
|
121
|
+
``compute-sanitizer``/``nsys`` and bounds checks in the array views
|
|
122
|
+
(no ``-G``: NVRTC does not support it).
|
|
123
|
+
"""
|
|
123
124
|
|
|
124
125
|
|
|
125
126
|
class CudaArguments:
|
|
@@ -192,10 +192,11 @@ def memory_info() -> tuple[int, int] | None:
|
|
|
192
192
|
return cp.cuda.runtime.memGetInfo()
|
|
193
193
|
|
|
194
194
|
|
|
195
|
-
#: Dynamic shared memory per block that every CUDA device provides without an
|
|
196
|
-
#: opt-in (48 KiB); also the answer of :func:`max_shared_memory_per_block`
|
|
197
|
-
#: without a GPU.
|
|
198
195
|
DEFAULT_SHARED_MEMORY_PER_BLOCK = 48 * 1024
|
|
196
|
+
"""Dynamic shared memory per block that every CUDA device provides without an
|
|
197
|
+
opt-in (48 KiB); also the answer of :func:`max_shared_memory_per_block`
|
|
198
|
+
without a GPU.
|
|
199
|
+
"""
|
|
199
200
|
|
|
200
201
|
|
|
201
202
|
def max_shared_memory_per_block(
|
|
@@ -64,10 +64,11 @@ def _on_device(arg: Any) -> bool:
|
|
|
64
64
|
return _is_device_array(arg) or callable(getattr(type(arg), "__cuda_args__", None))
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
#: Longest name a Fortran compiler accepts. Pyccel names the wrapper module of a
|
|
68
|
-
#: host kernel module ``bind_c_<module>``, so a module name longer than
|
|
69
|
-
#: ``63 - len("bind_c_")`` characters cannot be compiled with the Fortran backend.
|
|
70
67
|
FORTRAN_NAME_LIMIT = 63
|
|
68
|
+
"""Longest name a Fortran compiler accepts. Pyccel names the wrapper module of a
|
|
69
|
+
host kernel module ``bind_c_<module>``, so a module name longer than
|
|
70
|
+
``63 - len("bind_c_")`` characters cannot be compiled with the Fortran backend.
|
|
71
|
+
"""
|
|
71
72
|
|
|
72
73
|
|
|
73
74
|
def _pyccel_stub_parameters(function: Any) -> list[str] | None:
|
|
@@ -29,7 +29,6 @@ from typing import Any
|
|
|
29
29
|
|
|
30
30
|
import numpy as np
|
|
31
31
|
|
|
32
|
-
#: The subpackages of ``cupyx.scipy``; the same as ``_scipy_backend.SUBMODULES``.
|
|
33
32
|
SUBPACKAGES = (
|
|
34
33
|
"fft",
|
|
35
34
|
"fftpack",
|
|
@@ -44,21 +43,19 @@ SUBPACKAGES = (
|
|
|
44
43
|
"special",
|
|
45
44
|
"stats",
|
|
46
45
|
)
|
|
46
|
+
"""The subpackages of ``cupyx.scipy``; the same as ``_scipy_backend.SUBMODULES``."""
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def _names(text: str) -> frozenset[str]:
|
|
50
50
|
return frozenset(text.split())
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
#: The CuPy release whose ``cupyx.scipy`` names :data:`NAMES` lists: the oldest
|
|
54
|
-
#: supported one (``cunumpy.xp.MIN_CUPY_VERSION``), so code that runs on the
|
|
55
|
-
#: fake runs on every supported CuPy. Newer CuPy releases have more names.
|
|
56
53
|
NAMES_VERSION = "14.0.0"
|
|
54
|
+
"""The CuPy release whose ``cupyx.scipy`` names :data:`NAMES` lists: the oldest
|
|
55
|
+
supported one (``cunumpy.xp.MIN_CUPY_VERSION``), so code that runs on the
|
|
56
|
+
fake runs on every supported CuPy. Newer CuPy releases have more names.
|
|
57
|
+
"""
|
|
57
58
|
|
|
58
|
-
#: The public names of each ``cupyx.scipy`` subpackage in CuPy
|
|
59
|
-
#: :data:`NAMES_VERSION`. Check them against an installed CuPy with
|
|
60
|
-
#: ``python testing/cupyx_names.py`` (the GPU CI does, in
|
|
61
|
-
#: ``tests/unit/test_cupyx_names.py``).
|
|
62
59
|
NAMES = {
|
|
63
60
|
"fft": _names(
|
|
64
61
|
"""
|
|
@@ -193,6 +190,11 @@ NAMES = {
|
|
|
193
190
|
""",
|
|
194
191
|
),
|
|
195
192
|
}
|
|
193
|
+
"""The public names of each ``cupyx.scipy`` subpackage in CuPy
|
|
194
|
+
:data:`NAMES_VERSION`. Check them against an installed CuPy with
|
|
195
|
+
``python testing/cupyx_names.py`` (the GPU CI does, in
|
|
196
|
+
``tests/unit/test_cupyx_names.py``).
|
|
197
|
+
"""
|
|
196
198
|
|
|
197
199
|
|
|
198
200
|
def public_names(module: types.ModuleType) -> frozenset[str]:
|
|
@@ -438,9 +438,10 @@ class PyccelKernel:
|
|
|
438
438
|
return self._outputs
|
|
439
439
|
|
|
440
440
|
|
|
441
|
-
#: The names of the host implementations a kernel can have, see
|
|
442
|
-
#: :class:`~cunumpy.kernels.HostImplementations`.
|
|
443
441
|
HOST_IMPLEMENTATIONS = ("pyccel", "numba", "numpy", "python")
|
|
442
|
+
"""The names of the host implementations a kernel can have, see
|
|
443
|
+
:class:`~cunumpy.kernels.HostImplementations`.
|
|
444
|
+
"""
|
|
444
445
|
|
|
445
446
|
|
|
446
447
|
def _check_implementation(name: str | None) -> str | None:
|
|
@@ -536,8 +537,8 @@ def use_host_kernel_implementation(name: str | None) -> Iterator[None]:
|
|
|
536
537
|
_KERNEL_IMPLEMENTATION = previous
|
|
537
538
|
|
|
538
539
|
|
|
539
|
-
#: The names of the device implementations a kernel can have.
|
|
540
540
|
DEVICE_IMPLEMENTATIONS = ("cuda",)
|
|
541
|
+
"""The names of the device implementations a kernel can have."""
|
|
541
542
|
|
|
542
543
|
|
|
543
544
|
def _check_device_implementation(name: str | None) -> str | None:
|
|
@@ -950,7 +951,16 @@ def _with_unit_axis_strides(array: np.ndarray) -> np.ndarray:
|
|
|
950
951
|
extent = array.itemsize
|
|
951
952
|
for axis in reversed(range(array.ndim)):
|
|
952
953
|
if array.shape[axis] == 1:
|
|
953
|
-
|
|
954
|
+
# Any stride is valid for a length-1 axis, but Pyccel's C-order check
|
|
955
|
+
# wants each stride at least the extent of the axes inside it. Inside
|
|
956
|
+
# a longer axis, use exactly the C stride, so that the outer stride
|
|
957
|
+
# (e.g. 8 in a (2, 1) array with strides (8, 16)) still covers it;
|
|
958
|
+
# a leading length-1 axis may keep a larger stride (a row of a
|
|
959
|
+
# wider array, ``storage[1:2, :n]``).
|
|
960
|
+
if any(length > 1 for length in array.shape[:axis]):
|
|
961
|
+
strides[axis] = extent
|
|
962
|
+
else:
|
|
963
|
+
strides[axis] = max(strides[axis], extent)
|
|
954
964
|
else:
|
|
955
965
|
extent = strides[axis] * array.shape[axis]
|
|
956
966
|
if tuple(strides) == array.strides:
|
|
@@ -1052,6 +1062,18 @@ def _same_memory(buffer: Any, out: Any) -> bool:
|
|
|
1052
1062
|
)
|
|
1053
1063
|
|
|
1054
1064
|
|
|
1065
|
+
def _copy_back(buffer: Any, out: Any) -> None:
|
|
1066
|
+
"""Write `buffer` into `out`, on its own side, unless they share their memory."""
|
|
1067
|
+
if _same_memory(buffer, out):
|
|
1068
|
+
return
|
|
1069
|
+
if is_gpu(out) and not is_gpu(buffer):
|
|
1070
|
+
out[...] = to_cupy(buffer)
|
|
1071
|
+
elif not is_gpu(out) and is_gpu(buffer):
|
|
1072
|
+
out[...] = to_numpy(buffer)
|
|
1073
|
+
else:
|
|
1074
|
+
out[...] = buffer
|
|
1075
|
+
|
|
1076
|
+
|
|
1055
1077
|
class _KernelOutput:
|
|
1056
1078
|
"""The context manager of :func:`kernel_output` (a class: cheaper than a generator)."""
|
|
1057
1079
|
|
|
@@ -1070,16 +1092,8 @@ class _KernelOutput:
|
|
|
1070
1092
|
exc: BaseException | None,
|
|
1071
1093
|
traceback: TracebackType | None,
|
|
1072
1094
|
) -> None:
|
|
1073
|
-
if exc_type is
|
|
1074
|
-
|
|
1075
|
-
buffer, out = self._buffer, self._out
|
|
1076
|
-
if not _same_memory(buffer, out):
|
|
1077
|
-
if is_gpu(out) and not is_gpu(buffer):
|
|
1078
|
-
out[...] = to_cupy(buffer)
|
|
1079
|
-
elif not is_gpu(out) and is_gpu(buffer):
|
|
1080
|
-
out[...] = to_numpy(buffer)
|
|
1081
|
-
else:
|
|
1082
|
-
out[...] = buffer
|
|
1095
|
+
if exc_type is None:
|
|
1096
|
+
_copy_back(self._buffer, self._out)
|
|
1083
1097
|
|
|
1084
1098
|
|
|
1085
1099
|
def kernel_output(
|
|
@@ -1118,6 +1132,73 @@ def kernel_output(
|
|
|
1118
1132
|
return _KernelOutput(out, as_kernel_array(out, like, dtype, strided=strided))
|
|
1119
1133
|
|
|
1120
1134
|
|
|
1135
|
+
class _KernelOutputs:
|
|
1136
|
+
"""The context manager of :func:`kernel_outputs`."""
|
|
1137
|
+
|
|
1138
|
+
__slots__ = ("_buffers", "_outs")
|
|
1139
|
+
|
|
1140
|
+
def __init__(self, outs: tuple[Any, ...], buffers: tuple[Any, ...]) -> None:
|
|
1141
|
+
self._outs = outs
|
|
1142
|
+
self._buffers = buffers
|
|
1143
|
+
|
|
1144
|
+
def __enter__(self) -> tuple[Any, ...]:
|
|
1145
|
+
return self._buffers
|
|
1146
|
+
|
|
1147
|
+
def __exit__(
|
|
1148
|
+
self,
|
|
1149
|
+
exc_type: type[BaseException] | None,
|
|
1150
|
+
exc: BaseException | None,
|
|
1151
|
+
traceback: TracebackType | None,
|
|
1152
|
+
) -> None:
|
|
1153
|
+
if exc_type is None:
|
|
1154
|
+
for buffer, out in zip(self._buffers, self._outs, strict=True):
|
|
1155
|
+
_copy_back(buffer, out)
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
def kernel_outputs(
|
|
1159
|
+
*outs: Any, like: Any, dtype: Any = None, strided: bool = False
|
|
1160
|
+
) -> _KernelOutputs:
|
|
1161
|
+
"""Provide the output buffers of several arrays in one block.
|
|
1162
|
+
|
|
1163
|
+
As :func:`~cunumpy.kernels.kernel_output` for each of `outs`, with one
|
|
1164
|
+
context manager for all: cheaper for a kernel that writes several arrays,
|
|
1165
|
+
called at every step. Each buffer is its array itself if
|
|
1166
|
+
:func:`~cunumpy.kernels.as_kernel_array` takes it unchanged, else a
|
|
1167
|
+
converted copy written back into the array when the block ends without an
|
|
1168
|
+
error.
|
|
1169
|
+
|
|
1170
|
+
Parameters
|
|
1171
|
+
----------
|
|
1172
|
+
*outs : array
|
|
1173
|
+
The arrays the kernel should write.
|
|
1174
|
+
like : array
|
|
1175
|
+
A CuPy array for a device kernel, anything else for a host kernel.
|
|
1176
|
+
dtype : dtype, optional
|
|
1177
|
+
Required dtype of every buffer; by default any.
|
|
1178
|
+
strided : bool, optional
|
|
1179
|
+
As for :func:`~cunumpy.kernels.as_kernel_array`. Default False.
|
|
1180
|
+
|
|
1181
|
+
Returns
|
|
1182
|
+
-------
|
|
1183
|
+
context manager
|
|
1184
|
+
Yields the tuple of buffers to pass to the kernel, in the order of
|
|
1185
|
+
`outs`.
|
|
1186
|
+
|
|
1187
|
+
Examples
|
|
1188
|
+
--------
|
|
1189
|
+
>>> x = np.zeros(2)
|
|
1190
|
+
>>> counts = np.zeros(2, dtype=np.float32)
|
|
1191
|
+
>>> with xp.kernels.kernel_outputs(x, counts, like=x, dtype=float) as (a, b):
|
|
1192
|
+
... a[:] = 1.0 # x itself
|
|
1193
|
+
... b[:] = 2.5 # a float64 copy, written back into counts
|
|
1194
|
+
>>> x, counts
|
|
1195
|
+
(array([1., 1.]), array([2.5, 2.5], dtype=float32))
|
|
1196
|
+
"""
|
|
1197
|
+
return _KernelOutputs(
|
|
1198
|
+
outs, tuple(as_kernel_array(out, like, dtype, strided=strided) for out in outs)
|
|
1199
|
+
)
|
|
1200
|
+
|
|
1201
|
+
|
|
1121
1202
|
_SCALAR_ANNOTATIONS = {"int", "float", "bool", "complex", "str"}
|
|
1122
1203
|
|
|
1123
1204
|
|
|
@@ -33,8 +33,8 @@ __all__ = [
|
|
|
33
33
|
"morton_scales",
|
|
34
34
|
]
|
|
35
35
|
|
|
36
|
-
#: Largest number of bits per axis that fits a uint64 key, by dimension.
|
|
37
36
|
MAX_MORTON_LEVELS = {2: 32, 3: 21}
|
|
37
|
+
"""Largest number of bits per axis that fits a uint64 key, by dimension."""
|
|
38
38
|
|
|
39
39
|
_SPREAD = {
|
|
40
40
|
2: (
|