pyopencl 2025.2.5__cp311-cp311-win_amd64.whl → 2025.2.7__cp311-cp311-win_amd64.whl
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.
Potentially problematic release.
This version of pyopencl might be problematic. Click here for more details.
- pyopencl/_cl.cp311-win_amd64.pyd +0 -0
- pyopencl/_cl.pyi +10 -7
- pyopencl/_monkeypatch.py +40 -5
- pyopencl/algorithm.py +1 -1
- pyopencl/array.py +214 -125
- pyopencl/cache.py +1 -1
- pyopencl/characterize/__init__.py +2 -4
- pyopencl/clmath.py +0 -1
- pyopencl/cltypes.py +42 -27
- pyopencl/compyte/array.py +9 -39
- pyopencl/compyte/dtypes.py +9 -11
- pyopencl/compyte/pyproject.toml +0 -3
- pyopencl/elementwise.py +223 -113
- pyopencl/scan.py +30 -25
- pyopencl/tools.py +327 -212
- {pyopencl-2025.2.5.dist-info → pyopencl-2025.2.7.dist-info}/METADATA +3 -4
- {pyopencl-2025.2.5.dist-info → pyopencl-2025.2.7.dist-info}/RECORD +19 -19
- {pyopencl-2025.2.5.dist-info → pyopencl-2025.2.7.dist-info}/WHEEL +1 -1
- {pyopencl-2025.2.5.dist-info → pyopencl-2025.2.7.dist-info}/licenses/LICENSE +0 -0
pyopencl/array.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""CL device arrays."""
|
|
2
2
|
|
|
3
|
-
# NOTE: for elwise_kernel_runner which adds keyword arguments
|
|
4
|
-
# pylint:disable=unexpected-keyword-arg
|
|
5
3
|
from __future__ import annotations
|
|
6
4
|
|
|
7
5
|
|
|
@@ -41,12 +39,14 @@ from typing import (
|
|
|
41
39
|
Concatenate,
|
|
42
40
|
Literal,
|
|
43
41
|
ParamSpec,
|
|
42
|
+
TypeAlias,
|
|
43
|
+
TypeVar,
|
|
44
44
|
cast,
|
|
45
45
|
)
|
|
46
46
|
from warnings import warn
|
|
47
47
|
|
|
48
48
|
import numpy as np
|
|
49
|
-
from typing_extensions import Self, override
|
|
49
|
+
from typing_extensions import Self, TypeIs, override
|
|
50
50
|
|
|
51
51
|
import pyopencl as cl
|
|
52
52
|
import pyopencl.elementwise as elementwise
|
|
@@ -76,6 +76,9 @@ else:
|
|
|
76
76
|
_SVMPointer_or_nothing = ()
|
|
77
77
|
|
|
78
78
|
|
|
79
|
+
ArrayT = TypeVar("ArrayT", bound="Array")
|
|
80
|
+
|
|
81
|
+
|
|
79
82
|
class _NoValue:
|
|
80
83
|
pass
|
|
81
84
|
|
|
@@ -213,7 +216,7 @@ def _splay(
|
|
|
213
216
|
group_count = max_groups
|
|
214
217
|
work_items_per_group = max_work_items
|
|
215
218
|
|
|
216
|
-
# print("n
|
|
219
|
+
# print(f"n:{n} gc:{group_count} wipg:{work_items_per_group}")
|
|
217
220
|
return (group_count*work_items_per_group,), (work_items_per_group,)
|
|
218
221
|
|
|
219
222
|
|
|
@@ -246,14 +249,13 @@ def elwise_kernel_runner(
|
|
|
246
249
|
assert queue is not None
|
|
247
250
|
|
|
248
251
|
knl = kernel_getter(out, *args, **kwargs)
|
|
249
|
-
|
|
252
|
+
gs, ls = out._get_sizes(queue, knl.get_work_group_info(
|
|
250
253
|
cl.kernel_work_group_info.WORK_GROUP_SIZE,
|
|
251
254
|
queue.device))
|
|
252
|
-
gs, ls = out._get_sizes(queue, work_group_info)
|
|
253
255
|
|
|
254
256
|
knl_args = (out, *args, out.size)
|
|
255
257
|
if ARRAY_KERNEL_EXEC_HOOK is not None:
|
|
256
|
-
return ARRAY_KERNEL_EXEC_HOOK(
|
|
258
|
+
return ARRAY_KERNEL_EXEC_HOOK(
|
|
257
259
|
knl, queue, gs, ls, *knl_args, wait_for=wait_for)
|
|
258
260
|
else:
|
|
259
261
|
return knl(queue, gs, ls, *knl_args, wait_for=wait_for)
|
|
@@ -289,6 +291,12 @@ _ARRAY_GET_SIZES_CACHE: \
|
|
|
289
291
|
_BOOL_DTYPE = np.dtype(np.int8)
|
|
290
292
|
_NOT_PRESENT = object()
|
|
291
293
|
|
|
294
|
+
ScalarLike: TypeAlias = int | float | complex | np.number[Any]
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def _is_scalar(s: object) -> TypeIs[ScalarLike]:
|
|
298
|
+
return isinstance(s, SCALAR_CLASSES)
|
|
299
|
+
|
|
292
300
|
|
|
293
301
|
class Array:
|
|
294
302
|
"""A :class:`numpy.ndarray` work-alike that stores its data and performs
|
|
@@ -478,16 +486,6 @@ class Array:
|
|
|
478
486
|
|
|
479
487
|
__array_priority__: ClassVar[int] = 100
|
|
480
488
|
|
|
481
|
-
queue: cl.CommandQueue | None
|
|
482
|
-
shape: tuple[int, ...]
|
|
483
|
-
dtype: np.dtype[Any]
|
|
484
|
-
strides: tuple[int, ...]
|
|
485
|
-
events: list[cl.Event]
|
|
486
|
-
nbytes: int
|
|
487
|
-
size: int
|
|
488
|
-
allocator: Allocator | None
|
|
489
|
-
base_data: cl.MemoryObjectHolder | cl.SVMPointer | None
|
|
490
|
-
|
|
491
489
|
def __init__(
|
|
492
490
|
self,
|
|
493
491
|
cq: cl.Context | cl.CommandQueue | None,
|
|
@@ -568,7 +566,7 @@ class Array:
|
|
|
568
566
|
dtype = np.dtype(dtype)
|
|
569
567
|
|
|
570
568
|
try:
|
|
571
|
-
shape = tuple(shape)
|
|
569
|
+
shape = tuple(shape)
|
|
572
570
|
except TypeError as err:
|
|
573
571
|
if not isinstance(shape, (int, np.integer)):
|
|
574
572
|
raise TypeError(
|
|
@@ -587,7 +585,7 @@ class Array:
|
|
|
587
585
|
raise ValueError(f"negative dimensions are not allowed: {shape}")
|
|
588
586
|
if np.any([np.array([s]).dtype.kind not in ["u", "i"] for s in shape]):
|
|
589
587
|
raise ValueError(
|
|
590
|
-
"
|
|
588
|
+
f"invalid shape {shape} (all dimensions must be integers)")
|
|
591
589
|
size = np.prod(shape_array, dtype=np.uint64).item()
|
|
592
590
|
|
|
593
591
|
if strides is None:
|
|
@@ -624,34 +622,37 @@ class Array:
|
|
|
624
622
|
if alloc_nbytes < 0:
|
|
625
623
|
raise ValueError("cannot allocate CL buffer with negative size")
|
|
626
624
|
|
|
627
|
-
|
|
628
|
-
self.shape = shape
|
|
629
|
-
self.dtype = dtype
|
|
630
|
-
self.strides = strides
|
|
631
|
-
self.events = [] if events is None else events
|
|
632
|
-
self.nbytes = alloc_nbytes
|
|
633
|
-
self.size = size
|
|
634
|
-
self.allocator = allocator
|
|
635
|
-
|
|
625
|
+
base_data = None
|
|
636
626
|
if data is None:
|
|
637
627
|
if alloc_nbytes == 0:
|
|
638
|
-
|
|
628
|
+
base_data = None
|
|
639
629
|
|
|
640
630
|
else:
|
|
641
|
-
if
|
|
631
|
+
if allocator is None:
|
|
642
632
|
if context is None and queue is not None:
|
|
643
633
|
context = queue.context
|
|
644
634
|
|
|
645
|
-
|
|
646
|
-
|
|
635
|
+
assert context is not None
|
|
636
|
+
base_data = cl.Buffer(
|
|
637
|
+
context, cl.mem_flags.READ_WRITE, alloc_nbytes)
|
|
647
638
|
else:
|
|
648
|
-
|
|
639
|
+
base_data = allocator(alloc_nbytes)
|
|
649
640
|
else:
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
self.
|
|
653
|
-
self.context = context
|
|
654
|
-
self.
|
|
641
|
+
base_data = data
|
|
642
|
+
|
|
643
|
+
self.queue: cl.CommandQueue | None = queue
|
|
644
|
+
self.context: cl.Context | None = context
|
|
645
|
+
self.shape: tuple[int, ...] = shape
|
|
646
|
+
self.dtype: np.dtype[Any] = dtype
|
|
647
|
+
self.strides: tuple[int, ...] = strides
|
|
648
|
+
self.events: list[cl.Event] = [] if events is None else events
|
|
649
|
+
self.nbytes: int = alloc_nbytes
|
|
650
|
+
self.size: int = size
|
|
651
|
+
self.allocator: Allocator | None = allocator
|
|
652
|
+
self.base_data: cl.MemoryObjectHolder | cl.SVMPointer | None = base_data
|
|
653
|
+
self.offset: int = offset
|
|
654
|
+
|
|
655
|
+
self._flags: _ArrayFlags | None = _flags
|
|
655
656
|
|
|
656
657
|
if __debug__:
|
|
657
658
|
if queue is not None and isinstance(
|
|
@@ -664,11 +665,11 @@ class Array:
|
|
|
664
665
|
InconsistentOpenCLQueueWarning, stacklevel=2)
|
|
665
666
|
|
|
666
667
|
@property
|
|
667
|
-
def ndim(self):
|
|
668
|
+
def ndim(self) -> int:
|
|
668
669
|
return len(self.shape)
|
|
669
670
|
|
|
670
671
|
@property
|
|
671
|
-
def data(self):
|
|
672
|
+
def data(self) -> cl.MemoryObjectHolder | cl.SVMPointer | None:
|
|
672
673
|
if self.offset:
|
|
673
674
|
raise ArrayHasOffsetError()
|
|
674
675
|
else:
|
|
@@ -679,6 +680,7 @@ class Array:
|
|
|
679
680
|
f = self._flags
|
|
680
681
|
if f is None:
|
|
681
682
|
self._flags = f = _ArrayFlags(self)
|
|
683
|
+
|
|
682
684
|
return f
|
|
683
685
|
|
|
684
686
|
def _new_with_changes(self,
|
|
@@ -899,14 +901,16 @@ class Array:
|
|
|
899
901
|
|
|
900
902
|
return result
|
|
901
903
|
|
|
902
|
-
|
|
904
|
+
@override
|
|
905
|
+
def __str__(self) -> str:
|
|
903
906
|
if self.queue is None:
|
|
904
907
|
return (f"<cl.{type(self).__name__} {self.shape} of {self.dtype} "
|
|
905
908
|
"without queue, call with_queue()>")
|
|
906
909
|
|
|
907
910
|
return str(self.get())
|
|
908
911
|
|
|
909
|
-
|
|
912
|
+
@override
|
|
913
|
+
def __repr__(self) -> str:
|
|
910
914
|
if self.queue is None:
|
|
911
915
|
return (f"<cl.{type(self).__name__} {self.shape} of {self.dtype} "
|
|
912
916
|
f"at {id(self):x} without queue, call with_queue()>")
|
|
@@ -922,49 +926,69 @@ class Array:
|
|
|
922
926
|
|
|
923
927
|
return result
|
|
924
928
|
|
|
925
|
-
def safely_stringify_for_pudb(self):
|
|
929
|
+
def safely_stringify_for_pudb(self) -> str:
|
|
926
930
|
return f"cl.{type(self).__name__} {self.dtype} {self.shape}"
|
|
927
931
|
|
|
928
|
-
|
|
932
|
+
@override
|
|
933
|
+
def __hash__(self) -> int:
|
|
929
934
|
raise TypeError("pyopencl arrays are not hashable.")
|
|
930
935
|
|
|
931
936
|
# {{{ kernel invocation wrappers
|
|
932
937
|
|
|
933
938
|
@staticmethod
|
|
934
939
|
@elwise_kernel_runner
|
|
935
|
-
def _axpbyz(out
|
|
936
|
-
|
|
940
|
+
def _axpbyz(out: Array,
|
|
941
|
+
a: ScalarLike,
|
|
942
|
+
x: Array,
|
|
943
|
+
b: ScalarLike,
|
|
944
|
+
y: Array,
|
|
945
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
946
|
+
"""Compute ``out = a*x + b*y``,
|
|
937
947
|
where *other* is an array."""
|
|
938
|
-
|
|
939
|
-
|
|
948
|
+
x_shape = x.shape
|
|
949
|
+
y_shape = y.shape
|
|
940
950
|
out_shape = out.shape
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
951
|
+
|
|
952
|
+
assert out.context is not None
|
|
953
|
+
assert (x_shape == y_shape == out_shape
|
|
954
|
+
or (x_shape == () and y_shape == out_shape)
|
|
955
|
+
or (y_shape == () and x_shape == out_shape))
|
|
956
|
+
|
|
944
957
|
return elementwise.get_axpbyz_kernel(
|
|
945
|
-
out.context,
|
|
946
|
-
x_is_scalar=(
|
|
947
|
-
y_is_scalar=(
|
|
958
|
+
out.context, x.dtype, y.dtype, out.dtype,
|
|
959
|
+
x_is_scalar=(x_shape == ()),
|
|
960
|
+
y_is_scalar=(y_shape == ()))
|
|
948
961
|
|
|
949
962
|
@staticmethod
|
|
950
963
|
@elwise_kernel_runner
|
|
951
|
-
def _axpbz(out
|
|
964
|
+
def _axpbz(out: Array,
|
|
965
|
+
a: ScalarLike,
|
|
966
|
+
x: Array,
|
|
967
|
+
b: ScalarLike,
|
|
968
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
952
969
|
"""Compute ``z = a * x + b``, where *b* is a scalar."""
|
|
953
|
-
a = np.array(a)
|
|
954
|
-
b = np.array(b)
|
|
955
970
|
assert out.shape == x.shape
|
|
956
|
-
|
|
957
|
-
|
|
971
|
+
assert out.context is not None
|
|
972
|
+
|
|
973
|
+
return elementwise.get_axpbz_kernel(
|
|
974
|
+
out.context,
|
|
975
|
+
np.array(a).dtype, x.dtype, np.array(b).dtype, out.dtype)
|
|
958
976
|
|
|
959
977
|
@staticmethod
|
|
960
978
|
@elwise_kernel_runner
|
|
961
|
-
def _elwise_multiply(out
|
|
979
|
+
def _elwise_multiply(out: Array,
|
|
980
|
+
a: Array,
|
|
981
|
+
b: Array,
|
|
982
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
962
983
|
a_shape = a.shape
|
|
963
984
|
b_shape = b.shape
|
|
964
985
|
out_shape = out.shape
|
|
986
|
+
|
|
965
987
|
assert (a_shape == b_shape == out_shape
|
|
966
988
|
or (a_shape == () and b_shape == out_shape)
|
|
967
989
|
or (b_shape == () and a_shape == out_shape))
|
|
990
|
+
assert a.context is not None
|
|
991
|
+
|
|
968
992
|
return elementwise.get_multiply_kernel(
|
|
969
993
|
a.context, a.dtype, b.dtype, out.dtype,
|
|
970
994
|
x_is_scalar=(a_shape == ()),
|
|
@@ -973,19 +997,27 @@ class Array:
|
|
|
973
997
|
|
|
974
998
|
@staticmethod
|
|
975
999
|
@elwise_kernel_runner
|
|
976
|
-
def _rdiv_scalar(out
|
|
977
|
-
|
|
1000
|
+
def _rdiv_scalar(out: Array,
|
|
1001
|
+
ary: Array,
|
|
1002
|
+
other: ScalarLike,
|
|
1003
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
1004
|
+
assert out.context is not None
|
|
978
1005
|
assert out.shape == ary.shape
|
|
1006
|
+
|
|
979
1007
|
return elementwise.get_rdivide_elwise_kernel(
|
|
980
|
-
out.context, ary.dtype, other.dtype, out.dtype)
|
|
1008
|
+
out.context, ary.dtype, np.array(other).dtype, out.dtype)
|
|
981
1009
|
|
|
982
1010
|
@staticmethod
|
|
983
1011
|
@elwise_kernel_runner
|
|
984
|
-
def _div(out
|
|
1012
|
+
def _div(out: Array,
|
|
1013
|
+
self: Array,
|
|
1014
|
+
other: Array,
|
|
1015
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
985
1016
|
"""Divides an array by another array."""
|
|
986
1017
|
assert (self.shape == other.shape == out.shape
|
|
987
1018
|
or (self.shape == () and other.shape == out.shape)
|
|
988
1019
|
or (other.shape == () and self.shape == out.shape))
|
|
1020
|
+
assert self.context is not None
|
|
989
1021
|
|
|
990
1022
|
return elementwise.get_divide_kernel(self.context,
|
|
991
1023
|
self.dtype, other.dtype, out.dtype,
|
|
@@ -994,15 +1026,18 @@ class Array:
|
|
|
994
1026
|
|
|
995
1027
|
@staticmethod
|
|
996
1028
|
@elwise_kernel_runner
|
|
997
|
-
def _fill(result, scalar):
|
|
1029
|
+
def _fill(result: Array, scalar: ScalarLike) -> cl.Kernel:
|
|
1030
|
+
assert result.context is not None
|
|
998
1031
|
return elementwise.get_fill_kernel(result.context, result.dtype)
|
|
999
1032
|
|
|
1000
1033
|
@staticmethod
|
|
1001
1034
|
@elwise_kernel_runner
|
|
1002
|
-
def _abs(result, arg):
|
|
1035
|
+
def _abs(result: Array, arg: Array) -> cl.Kernel:
|
|
1036
|
+
assert arg.context is not None
|
|
1037
|
+
|
|
1003
1038
|
if arg.dtype.kind == "c":
|
|
1004
1039
|
from pyopencl.elementwise import complex_dtype_to_name
|
|
1005
|
-
fname = "
|
|
1040
|
+
fname = f"{complex_dtype_to_name(arg.dtype)}_abs"
|
|
1006
1041
|
elif arg.dtype.kind == "f":
|
|
1007
1042
|
fname = "fabs"
|
|
1008
1043
|
elif arg.dtype.kind in ["u", "i"]:
|
|
@@ -1015,63 +1050,83 @@ class Array:
|
|
|
1015
1050
|
|
|
1016
1051
|
@staticmethod
|
|
1017
1052
|
@elwise_kernel_runner
|
|
1018
|
-
def _real(result, arg):
|
|
1053
|
+
def _real(result: Array, arg: Array) -> cl.Kernel:
|
|
1019
1054
|
from pyopencl.elementwise import complex_dtype_to_name
|
|
1020
|
-
|
|
1055
|
+
|
|
1056
|
+
assert arg.context is not None
|
|
1057
|
+
fname = f"{complex_dtype_to_name(arg.dtype)}_real"
|
|
1058
|
+
|
|
1021
1059
|
return elementwise.get_unary_func_kernel(
|
|
1022
1060
|
arg.context, fname, arg.dtype, out_dtype=result.dtype)
|
|
1023
1061
|
|
|
1024
1062
|
@staticmethod
|
|
1025
1063
|
@elwise_kernel_runner
|
|
1026
|
-
def _imag(result, arg):
|
|
1064
|
+
def _imag(result: Array, arg: Array) -> cl.Kernel:
|
|
1027
1065
|
from pyopencl.elementwise import complex_dtype_to_name
|
|
1028
|
-
|
|
1066
|
+
|
|
1067
|
+
assert arg.context is not None
|
|
1068
|
+
fname = f"{complex_dtype_to_name(arg.dtype)}_imag"
|
|
1069
|
+
|
|
1029
1070
|
return elementwise.get_unary_func_kernel(
|
|
1030
1071
|
arg.context, fname, arg.dtype, out_dtype=result.dtype)
|
|
1031
1072
|
|
|
1032
1073
|
@staticmethod
|
|
1033
1074
|
@elwise_kernel_runner
|
|
1034
|
-
def _conj(result, arg):
|
|
1075
|
+
def _conj(result: Array, arg: Array) -> cl.Kernel:
|
|
1035
1076
|
from pyopencl.elementwise import complex_dtype_to_name
|
|
1036
|
-
|
|
1077
|
+
|
|
1078
|
+
assert arg.context is not None
|
|
1079
|
+
fname = f"{complex_dtype_to_name(arg.dtype)}_conj"
|
|
1080
|
+
|
|
1037
1081
|
return elementwise.get_unary_func_kernel(
|
|
1038
1082
|
arg.context, fname, arg.dtype, out_dtype=result.dtype)
|
|
1039
1083
|
|
|
1040
1084
|
@staticmethod
|
|
1041
1085
|
@elwise_kernel_runner
|
|
1042
|
-
def _pow_scalar(result
|
|
1043
|
-
|
|
1086
|
+
def _pow_scalar(result: Array,
|
|
1087
|
+
ary: Array,
|
|
1088
|
+
exponent: ScalarLike) -> cl.Kernel:
|
|
1089
|
+
assert result.context is not None
|
|
1044
1090
|
return elementwise.get_pow_kernel(result.context,
|
|
1045
|
-
ary.dtype, exponent.dtype, result.dtype,
|
|
1091
|
+
ary.dtype, np.array(exponent).dtype, result.dtype,
|
|
1046
1092
|
is_base_array=True, is_exp_array=False)
|
|
1047
1093
|
|
|
1048
1094
|
@staticmethod
|
|
1049
1095
|
@elwise_kernel_runner
|
|
1050
|
-
def _rpow_scalar(result
|
|
1051
|
-
|
|
1096
|
+
def _rpow_scalar(result: Array,
|
|
1097
|
+
base: ScalarLike,
|
|
1098
|
+
exponent: Array) -> cl.Kernel:
|
|
1099
|
+
assert result.context is not None
|
|
1052
1100
|
return elementwise.get_pow_kernel(result.context,
|
|
1053
|
-
base.dtype, exponent.dtype, result.dtype,
|
|
1101
|
+
np.array(base).dtype, exponent.dtype, result.dtype,
|
|
1054
1102
|
is_base_array=False, is_exp_array=True)
|
|
1055
1103
|
|
|
1056
1104
|
@staticmethod
|
|
1057
1105
|
@elwise_kernel_runner
|
|
1058
|
-
def _pow_array(result
|
|
1106
|
+
def _pow_array(result: Array,
|
|
1107
|
+
base: Array,
|
|
1108
|
+
exponent: Array) -> cl.Kernel:
|
|
1109
|
+
assert result.context is not None
|
|
1059
1110
|
return elementwise.get_pow_kernel(
|
|
1060
1111
|
result.context, base.dtype, exponent.dtype, result.dtype,
|
|
1061
1112
|
is_base_array=True, is_exp_array=True)
|
|
1062
1113
|
|
|
1063
1114
|
@staticmethod
|
|
1064
1115
|
@elwise_kernel_runner
|
|
1065
|
-
def _reverse(result, ary):
|
|
1116
|
+
def _reverse(result: Array, ary: Array) -> cl.Kernel:
|
|
1117
|
+
assert result.context is not None
|
|
1066
1118
|
return elementwise.get_reverse_kernel(result.context, ary.dtype)
|
|
1067
1119
|
|
|
1068
1120
|
@staticmethod
|
|
1069
1121
|
@elwise_kernel_runner
|
|
1070
|
-
def _copy(dest, src):
|
|
1122
|
+
def _copy(dest: Array, src: Array) -> cl.Kernel:
|
|
1123
|
+
assert dest.context is not None
|
|
1071
1124
|
return elementwise.get_copy_kernel(
|
|
1072
1125
|
dest.context, dest.dtype, src.dtype)
|
|
1073
1126
|
|
|
1074
|
-
def _new_like_me(self,
|
|
1127
|
+
def _new_like_me(self,
|
|
1128
|
+
dtype: DTypeLike = None,
|
|
1129
|
+
queue: cl.CommandQueue | None = None) -> Self:
|
|
1075
1130
|
if dtype is None:
|
|
1076
1131
|
dtype = self.dtype
|
|
1077
1132
|
strides = self.strides
|
|
@@ -1095,20 +1150,26 @@ class Array:
|
|
|
1095
1150
|
|
|
1096
1151
|
@staticmethod
|
|
1097
1152
|
@elwise_kernel_runner
|
|
1098
|
-
def _scalar_binop(out, a, b
|
|
1153
|
+
def _scalar_binop(out: Array, a: Array, b: ScalarLike, op: str,
|
|
1154
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
1155
|
+
assert out.context is not None
|
|
1099
1156
|
return elementwise.get_array_scalar_binop_kernel(
|
|
1100
1157
|
out.context, op, out.dtype, a.dtype,
|
|
1101
1158
|
np.array(b).dtype)
|
|
1102
1159
|
|
|
1103
1160
|
@staticmethod
|
|
1104
1161
|
@elwise_kernel_runner
|
|
1105
|
-
def _array_binop(out, a, b
|
|
1162
|
+
def _array_binop(out: Array, a: Array, b: Array, op: str,
|
|
1163
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
1106
1164
|
a_shape = a.shape
|
|
1107
1165
|
b_shape = b.shape
|
|
1108
1166
|
out_shape = out.shape
|
|
1167
|
+
|
|
1109
1168
|
assert (a_shape == b_shape == out_shape
|
|
1110
1169
|
or (a_shape == () and b_shape == out_shape)
|
|
1111
1170
|
or (b_shape == () and a_shape == out_shape))
|
|
1171
|
+
assert out.context is not None
|
|
1172
|
+
|
|
1112
1173
|
return elementwise.get_array_binop_kernel(
|
|
1113
1174
|
out.context, op, out.dtype, a.dtype, b.dtype,
|
|
1114
1175
|
a_is_scalar=(a_shape == ()),
|
|
@@ -1116,9 +1177,12 @@ class Array:
|
|
|
1116
1177
|
|
|
1117
1178
|
@staticmethod
|
|
1118
1179
|
@elwise_kernel_runner
|
|
1119
|
-
def _unop(out, a
|
|
1180
|
+
def _unop(out: Array, a: Array, op: str,
|
|
1181
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
1182
|
+
assert out.context is not None
|
|
1120
1183
|
if out.shape != a.shape:
|
|
1121
1184
|
raise ValueError("shapes of arguments do not match")
|
|
1185
|
+
|
|
1122
1186
|
return elementwise.get_unop_kernel(
|
|
1123
1187
|
out.context, op, a.dtype, out.dtype)
|
|
1124
1188
|
|
|
@@ -1590,7 +1654,7 @@ class Array:
|
|
|
1590
1654
|
result.add_event(self._reverse(result, self))
|
|
1591
1655
|
return result
|
|
1592
1656
|
|
|
1593
|
-
def astype(self, dtype, queue: cl.CommandQueue | None = None):
|
|
1657
|
+
def astype(self, dtype: DTypeLike, queue: cl.CommandQueue | None = None):
|
|
1594
1658
|
"""Return a copy of *self*, cast to *dtype*."""
|
|
1595
1659
|
if dtype == self.dtype:
|
|
1596
1660
|
return self.copy()
|
|
@@ -1636,15 +1700,26 @@ class Array:
|
|
|
1636
1700
|
|
|
1637
1701
|
@staticmethod
|
|
1638
1702
|
@elwise_kernel_runner
|
|
1639
|
-
def _scalar_comparison(out
|
|
1703
|
+
def _scalar_comparison(out: Array,
|
|
1704
|
+
a: Array,
|
|
1705
|
+
b: ScalarLike,
|
|
1706
|
+
op: str,
|
|
1707
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
1708
|
+
assert out.context is not None
|
|
1640
1709
|
return elementwise.get_array_scalar_comparison_kernel(
|
|
1641
1710
|
out.context, op, a.dtype)
|
|
1642
1711
|
|
|
1643
1712
|
@staticmethod
|
|
1644
1713
|
@elwise_kernel_runner
|
|
1645
|
-
def _array_comparison(out
|
|
1714
|
+
def _array_comparison(out: Array,
|
|
1715
|
+
a: Array,
|
|
1716
|
+
b: Array,
|
|
1717
|
+
op: str,
|
|
1718
|
+
queue: cl.CommandQueue | None = None) -> cl.Kernel:
|
|
1719
|
+
assert out.context is not None
|
|
1646
1720
|
if a.shape != b.shape:
|
|
1647
1721
|
raise ValueError("shapes of comparison arguments do not match")
|
|
1722
|
+
|
|
1648
1723
|
return elementwise.get_array_comparison_kernel(
|
|
1649
1724
|
out.context, op, a.dtype, b.dtype)
|
|
1650
1725
|
|
|
@@ -1810,8 +1885,7 @@ class Array:
|
|
|
1810
1885
|
|
|
1811
1886
|
order = kwargs.pop("order", "C")
|
|
1812
1887
|
if kwargs:
|
|
1813
|
-
raise TypeError("unexpected keyword arguments:
|
|
1814
|
-
% list(kwargs.keys()))
|
|
1888
|
+
raise TypeError(f"unexpected keyword arguments: {list(kwargs)}")
|
|
1815
1889
|
|
|
1816
1890
|
if order not in "CF":
|
|
1817
1891
|
raise ValueError("order must be either 'C' or 'F'")
|
|
@@ -2123,8 +2197,7 @@ class Array:
|
|
|
2123
2197
|
index_entry += array_shape
|
|
2124
2198
|
|
|
2125
2199
|
if not (0 <= index_entry < array_shape):
|
|
2126
|
-
raise IndexError(
|
|
2127
|
-
"subindex in axis %d out of range" % index_axis)
|
|
2200
|
+
raise IndexError(f"subindex in axis {index_axis} out of range")
|
|
2128
2201
|
|
|
2129
2202
|
new_offset += self.strides[array_axis]*index_entry
|
|
2130
2203
|
|
|
@@ -2154,7 +2227,7 @@ class Array:
|
|
|
2154
2227
|
index_axis += 1
|
|
2155
2228
|
|
|
2156
2229
|
else:
|
|
2157
|
-
raise IndexError("invalid subindex in axis
|
|
2230
|
+
raise IndexError(f"invalid subindex in axis {index_axis}")
|
|
2158
2231
|
|
|
2159
2232
|
while array_axis < len(self.shape):
|
|
2160
2233
|
new_shape.append(self.shape[array_axis])
|
|
@@ -2355,7 +2428,7 @@ def empty_like(
|
|
|
2355
2428
|
allocator=allocator)
|
|
2356
2429
|
|
|
2357
2430
|
|
|
2358
|
-
def zeros_like(ary):
|
|
2431
|
+
def zeros_like(ary: ArrayT) -> ArrayT:
|
|
2359
2432
|
"""Make a new, zero-initialized :class:`Array` having the same properties
|
|
2360
2433
|
as *other_ary*.
|
|
2361
2434
|
"""
|
|
@@ -2656,11 +2729,15 @@ def multi_put(
|
|
|
2656
2729
|
return []
|
|
2657
2730
|
|
|
2658
2731
|
from pytools import single_valued
|
|
2732
|
+
|
|
2659
2733
|
a_dtype = single_valued(a.dtype for a in arrays)
|
|
2660
2734
|
a_allocator = arrays[0].allocator
|
|
2735
|
+
|
|
2661
2736
|
context = dest_indices.context
|
|
2662
2737
|
queue = queue or dest_indices.queue
|
|
2663
2738
|
assert queue is not None
|
|
2739
|
+
assert context is not None
|
|
2740
|
+
|
|
2664
2741
|
if wait_for is None:
|
|
2665
2742
|
wait_for = []
|
|
2666
2743
|
wait_for = [*wait_for, *dest_indices.events]
|
|
@@ -2764,7 +2841,6 @@ def concatenate(arrays, axis=0, queue: cl.CommandQueue | None = None, allocator=
|
|
|
2764
2841
|
raise ValueError(
|
|
2765
2842
|
f"{i_ary}-th array has residual not matching other arrays")
|
|
2766
2843
|
|
|
2767
|
-
# pylint: disable=unsupported-assignment-operation
|
|
2768
2844
|
shape[axis] += ary.shape[axis]
|
|
2769
2845
|
|
|
2770
2846
|
# }}}
|
|
@@ -2960,18 +3036,18 @@ def _if_positive(result, criterion, then_, else_):
|
|
|
2960
3036
|
|
|
2961
3037
|
|
|
2962
3038
|
def if_positive(
|
|
2963
|
-
criterion,
|
|
2964
|
-
then_,
|
|
2965
|
-
else_,
|
|
2966
|
-
out=None,
|
|
3039
|
+
criterion: Array | ScalarLike,
|
|
3040
|
+
then_: Array | ScalarLike,
|
|
3041
|
+
else_: Array | ScalarLike,
|
|
3042
|
+
out: Array | None = None,
|
|
2967
3043
|
queue: cl.CommandQueue | None = None):
|
|
2968
3044
|
"""Return an array like *then_*, which, for the element at index *i*,
|
|
2969
3045
|
contains *then_[i]* if *criterion[i]>0*, else *else_[i]*.
|
|
2970
3046
|
"""
|
|
2971
3047
|
|
|
2972
|
-
is_then_scalar =
|
|
2973
|
-
is_else_scalar =
|
|
2974
|
-
if
|
|
3048
|
+
is_then_scalar = _is_scalar(then_)
|
|
3049
|
+
is_else_scalar = _is_scalar(else_)
|
|
3050
|
+
if _is_scalar(criterion) and is_then_scalar and is_else_scalar:
|
|
2975
3051
|
result = np.where(criterion, then_, else_)
|
|
2976
3052
|
|
|
2977
3053
|
if out is not None:
|
|
@@ -2981,53 +3057,60 @@ def if_positive(
|
|
|
2981
3057
|
return result
|
|
2982
3058
|
|
|
2983
3059
|
if is_then_scalar:
|
|
2984
|
-
|
|
3060
|
+
then_ary = np.array(then_)
|
|
3061
|
+
else:
|
|
3062
|
+
then_ary = then_
|
|
3063
|
+
|
|
3064
|
+
assert not _is_scalar(criterion)
|
|
2985
3065
|
|
|
2986
3066
|
if is_else_scalar:
|
|
2987
|
-
|
|
3067
|
+
else_ary = np.array(else_)
|
|
3068
|
+
else:
|
|
3069
|
+
else_ary = else_
|
|
2988
3070
|
|
|
2989
|
-
if
|
|
3071
|
+
if then_ary.dtype != else_ary.dtype:
|
|
2990
3072
|
raise ValueError(
|
|
2991
|
-
f"dtypes do not match:
|
|
2992
|
-
f"
|
|
3073
|
+
f"dtypes do not match: then_ary is '{then_ary.dtype}' and "
|
|
3074
|
+
f"else_ary is '{else_ary.dtype}'")
|
|
2993
3075
|
|
|
2994
|
-
if
|
|
3076
|
+
if then_ary.shape == () and else_ary.shape == ():
|
|
2995
3077
|
pass
|
|
2996
|
-
elif
|
|
2997
|
-
if not (criterion.shape ==
|
|
3078
|
+
elif then_ary.shape != () and else_ary.shape != ():
|
|
3079
|
+
if not (criterion.shape == then_ary.shape == else_ary.shape):
|
|
2998
3080
|
raise ValueError(
|
|
2999
3081
|
f"shapes do not match: 'criterion' has shape {criterion.shape}"
|
|
3000
|
-
f", '
|
|
3001
|
-
f"{
|
|
3002
|
-
elif
|
|
3003
|
-
if criterion.shape !=
|
|
3082
|
+
f", 'then_ary' has shape {then_ary.shape} and 'else_ary' has shape "
|
|
3083
|
+
f"{else_ary.shape}")
|
|
3084
|
+
elif then_ary.shape == ():
|
|
3085
|
+
if criterion.shape != else_ary.shape:
|
|
3004
3086
|
raise ValueError(
|
|
3005
3087
|
f"shapes do not match: 'criterion' has shape {criterion.shape}"
|
|
3006
|
-
f" and '
|
|
3007
|
-
elif
|
|
3008
|
-
if criterion.shape !=
|
|
3088
|
+
f" and 'else_ary' has shape {else_ary.shape}")
|
|
3089
|
+
elif else_ary.shape == ():
|
|
3090
|
+
if criterion.shape != then_ary.shape:
|
|
3009
3091
|
raise ValueError(
|
|
3010
3092
|
f"shapes do not match: 'criterion' has shape {criterion.shape}"
|
|
3011
|
-
f" and '
|
|
3093
|
+
f" and 'then_ary' has shape {then_ary.shape}")
|
|
3012
3094
|
else:
|
|
3013
3095
|
raise AssertionError()
|
|
3014
3096
|
|
|
3015
3097
|
if out is None:
|
|
3016
|
-
if
|
|
3098
|
+
if then_ary.shape != ():
|
|
3099
|
+
assert isinstance(then_ary, Array)
|
|
3017
3100
|
out = empty_like(
|
|
3018
|
-
|
|
3101
|
+
then_ary, criterion.queue, allocator=criterion.allocator)
|
|
3019
3102
|
else:
|
|
3020
3103
|
# Use same strides as criterion
|
|
3021
3104
|
cr_byte_strides = np.array(criterion.strides, dtype=np.int64)
|
|
3022
3105
|
cr_item_strides = cr_byte_strides // criterion.dtype.itemsize
|
|
3023
|
-
out_strides = tuple(cr_item_strides*
|
|
3106
|
+
out_strides = tuple(cr_item_strides*then_ary.dtype.itemsize)
|
|
3024
3107
|
|
|
3025
3108
|
out = type(criterion)(
|
|
3026
|
-
criterion.queue, criterion.shape,
|
|
3109
|
+
criterion.queue, criterion.shape, then_ary.dtype,
|
|
3027
3110
|
allocator=criterion.allocator,
|
|
3028
3111
|
strides=out_strides)
|
|
3029
3112
|
|
|
3030
|
-
event1 = _if_positive(out, criterion,
|
|
3113
|
+
event1 = _if_positive(out, criterion, then_ary, else_ary, queue=queue)
|
|
3031
3114
|
out.add_event(event1)
|
|
3032
3115
|
|
|
3033
3116
|
return out
|
|
@@ -3105,7 +3188,11 @@ def minimum(a, b, out=None, queue: cl.CommandQueue | None = None):
|
|
|
3105
3188
|
|
|
3106
3189
|
# {{{ logical ops
|
|
3107
3190
|
|
|
3108
|
-
def _logical_op(x1
|
|
3191
|
+
def _logical_op(x1: Array | ScalarLike,
|
|
3192
|
+
x2: Array | ScalarLike,
|
|
3193
|
+
out: Array | None,
|
|
3194
|
+
operator: str,
|
|
3195
|
+
queue: cl.CommandQueue | None = None) -> Array:
|
|
3109
3196
|
# NOTE: Copied from pycuda.gpuarray
|
|
3110
3197
|
assert operator in ["&&", "||"]
|
|
3111
3198
|
|
|
@@ -3129,6 +3216,7 @@ def _logical_op(x1, x2, out, operator, queue: cl.CommandQueue | None = None):
|
|
|
3129
3216
|
|
|
3130
3217
|
out = out or ary_arg._new_like_me(dtype=np.int8)
|
|
3131
3218
|
|
|
3219
|
+
assert queue is not None
|
|
3132
3220
|
assert out.shape == ary_arg.shape and out.dtype == np.int8
|
|
3133
3221
|
|
|
3134
3222
|
knl = elementwise.get_array_scalar_binop_kernel(
|
|
@@ -3153,6 +3241,7 @@ def _logical_op(x1, x2, out, operator, queue: cl.CommandQueue | None = None):
|
|
|
3153
3241
|
out = empty(queue, allocator=allocator,
|
|
3154
3242
|
shape=x1.shape, dtype=np.int8)
|
|
3155
3243
|
|
|
3244
|
+
assert queue is not None
|
|
3156
3245
|
assert out.shape == x1.shape and out.dtype == np.int8
|
|
3157
3246
|
|
|
3158
3247
|
knl = elementwise.get_array_binop_kernel(
|