Skip to content
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

NEP50 #8323

Open
wants to merge 49 commits into
base: main
Choose a base branch
from
Open

NEP50 #8323

wants to merge 49 commits into from

Conversation

ev-br
Copy link
Contributor

@ev-br ev-br commented May 9, 2024

Split off #8314 to keep the diff sizes under control.

Adapt the codebase to NEP 50 (https://numpy.org/neps/nep-0050-scalar-promotion.html). Unlike gh-8314, this PR can be run under NumPy 1.x using

$ export NPY_PROMOTION_STATE=weak
$ pytest ...

The main change is that under NEP 50, we have to keep track of "weak" scalars:

In [5]: (np.int8(1) + np.uint8(1)).dtype
Out[5]: dtype('int16')

In [6]: (1 + np.uint8(1)).dtype
Out[6]: dtype('uint8')

Implementation-wise, CuPy seems to convert python scalars to numpy scalars rather early in the game; thus we keep track of which arguments of ufuncs are python scalars, and take this into account when selecting ufunc loops.
So far am only doing it in ufuncs, will need to see if ElementwiseKernels / fusion loops / reductions are affected.

The goal is to make tests pass locally first with numpy 1.26.x & weak promotion rules, so that one can think of switching this on the CI. So far it's not even close: need to weed away lots of assumptions about the promotion rules in code and tests.

@leofang
Copy link
Member

leofang commented May 11, 2024

cc: @seberg for vis

@ev-br ev-br force-pushed the nep50 branch 4 times, most recently from 5cea763 to b5dced7 Compare May 13, 2024 09:50
@ev-br ev-br changed the title WIP: NEP50 NEP50 May 13, 2024
@ev-br
Copy link
Contributor Author

ev-br commented May 13, 2024

OK, this starts making sense. Locally I'm down to a handful of failures in jit compilation and fusion, and a first sanity review would be great. Also might be a good time to think how to switch it on the CI.

Also locally I'm having issues with float16 failures and several OOM errors, with or without weak promotion. Not sure what is the reason.

A breakdown of test results in test/cupy_tests is below the fold.

- [x] tests/cupy_tests/test_typing.py
- [x] tests/cupy_tests/test_init.py
- [-] tests/cupy_tests/test_numpy_interop.py
      2 OOM failures
- [x] tests/cupy_tests/test_ndim.py
- [x] tests/cupy_tests/test_type_routines.py
- [x] tests/cupy_tests/test_cublas.py

- [x] tests/cupy_tests/manipulation_tests/test_shape.py
- [x] tests/cupy_tests/manipulation_tests/test_kind.py
- [x] tests/cupy_tests/manipulation_tests/test_transpose.py
- [-] tests/cupy_tests/manipulation_tests/test_add_remove.py
      2 float16 fails
- [x] tests/cupy_tests/manipulation_tests/test_basic.py
      copyto: is in flux in numpy 2.0.0rc2, xfail for now
- [x] tests/cupy_tests/manipulation_tests/test_tiling.py
- [x] tests/cupy_tests/manipulation_tests/test_rearrange.py
- [x] tests/cupy_tests/manipulation_tests/test_dims.py
- [x] tests/cupy_tests/manipulation_tests/test_join.py
- [x] tests/cupy_tests/manipulation_tests/test_split.py

- [x] tests/cupy_tests/fft_tests/test_cache.py
- [x] tests/cupy_tests/fft_tests/test_callback.py
- [-] tests/cupy_tests/fft_tests/test_fft.py
      1 OOM TestFftAllocate::test_fft_allocate

- [x] tests/cupy_tests/core_tests/test_raw.py
- [-] tests/cupy_tests/core_tests/test_carray.py
      3 OOMs 32bit bounary
- [x] tests/cupy_tests/core_tests/test_flags.py
- [x] tests/cupy_tests/core_tests/test_internal.py
- [x] tests/cupy_tests/core_tests/test_ndarray_scatter.py
- [x] tests/cupy_tests/core_tests/test_core.py
- [-] tests/cupy_tests/core_tests/test_ndarray_reduction.py
      52 float16 fails
- [x] tests/cupy_tests/core_tests/test_ndarray_cuda_array_interface.py
- [x] tests/cupy_tests/core_tests/test_gufuncs.py
- [x] tests/cupy_tests/core_tests/test_ndarray_indexing.py
- [x] tests/cupy_tests/core_tests/test_ndarray.py
- [x] tests/cupy_tests/core_tests/test_ndarray_adv_indexing.py
- [x] tests/cupy_tests/core_tests/test_ndarray_unary_op.py
- [x] tests/cupy_tests/core_tests/test_ndarray_conversion.py
- [x] tests/cupy_tests/core_tests/test_ndarray_math.py
- [x] tests/cupy_tests/core_tests/test_scan.py
- [x] tests/cupy_tests/core_tests/test_userkernel.py
- [x] tests/cupy_tests/core_tests/test_ndarray_copy_and_view.py
- [-] tests/cupy_tests/core_tests/test_ufunc_methods.py
      2 float16 fails in UfuncReduce
- [x] tests/cupy_tests/core_tests/test_ndarray_complex_ops.py
- [x] tests/cupy_tests/core_tests/test_include.py
- [x] tests/cupy_tests/core_tests/test_array_function.py
- [x] tests/cupy_tests/core_tests/test_iter.py
- [x] tests/cupy_tests/core_tests/test_ndarray_owndata.py
- [x] tests/cupy_tests/core_tests/test_elementwise.py
- [x] tests/cupy_tests/core_tests/test_function.py
- [x] tests/cupy_tests/core_tests/test_ndarray_elementwise_op.py
- [x] tests/cupy_tests/core_tests/test_nep50_examples.py
- [x] tests/cupy_tests/core_tests/test_reduction.py
- [x] tests/cupy_tests/core_tests/test_ndarray_ufunc.py
- [x] tests/cupy_tests/core_tests/test_syncdetect.py
- [x] tests/cupy_tests/core_tests/test_cub_reduction.py
- [x] tests/cupy_tests/core_tests/test_ndarray_get.py
- [x] tests/cupy_tests/core_tests/test_ndarray_contiguity.py
- [x] tests/cupy_tests/core_tests/test_dlpack.py

- [x] tests/cupy_tests/core_tests/fusion_tests/test_example.py
- [x] tests/cupy_tests/core_tests/fusion_tests/test_array.py
- [x] tests/cupy_tests/core_tests/fusion_tests/test_routines.py
- [x] tests/cupy_tests/core_tests/fusion_tests/test_ufunc.py
- [x] tests/cupy_tests/core_tests/fusion_tests/test_optimization.py
- [x] tests/cupy_tests/core_tests/fusion_tests/test_reduction.py
- [x] tests/cupy_tests/core_tests/fusion_tests/test_kernel_cache.py
- [x] tests/cupy_tests/core_tests/fusion_tests/test_misc.py
- [x] tests/cupy_tests/core_tests/fusion_tests/test_indexing.py

- [x] tests/cupy_tests/logic_tests/test_comparison.py
- [x] tests/cupy_tests/logic_tests/test_truth.py
- [x] tests/cupy_tests/logic_tests/test_type_test.py
- [x] tests/cupy_tests/logic_tests/test_ops.py
- [x] tests/cupy_tests/logic_tests/test_content.py

- [-] tests/cupy_tests/lib_tests/test_shape_base.py
      1 float16 fails
- [-] tests/cupy_tests/lib_tests/test_polynomial.py
  
- [x] tests/cupy_tests/lib_tests/test_strided_tricks.py

- [x] tests/cupy_tests/random_tests/test_distributions.py
- [-] tests/cupy_tests/random_tests/test_sample.py
      3 float16 fails
- [x] tests/cupy_tests/random_tests/test_random.py
- [x] tests/cupy_tests/random_tests/test_init.py
- [-] tests/cupy_tests/random_tests/test_generator.py
      1 float16 fail
- [x] tests/cupy_tests/random_tests/test_bit_generator.py
- [-] tests/cupy_tests/random_tests/test_generator_api.py
      1 float16 fail
- [x] tests/cupy_tests/random_tests/test_permutations.py

- [x] tests/cupy_tests/math_tests/test_rational.py
- [x] tests/cupy_tests/math_tests/test_window.py
- [-] tests/cupy_tests/math_tests/test_special.py
      1 float16 (?) 
- [x] tests/cupy_tests/math_tests/test_hyperbolic.py
- [-] tests/cupy_tests/math_tests/test_matmul.py
      2 float16 fails
- [x] tests/cupy_tests/math_tests/test_explog.py
- [x] tests/cupy_tests/math_tests/test_arithmetic.py
- [x] tests/cupy_tests/math_tests/test_trigonometric.py
- [x] tests/cupy_tests/math_tests/test_rounding.py
- [x] tests/cupy_tests/math_tests/test_misc.py
- [x] tests/cupy_tests/math_tests/test_floating.py
- [-] tests/cupy_tests/math_tests/test_sumprod.py
      37 float16 fails + 1 OOM

- [x] tests/cupy_tests/testing_tests/test_array.py
- [x] tests/cupy_tests/testing_tests/test_loops.py
- [x] tests/cupy_tests/testing_tests/test_helper.py
- [x] tests/cupy_tests/testing_tests/test_parameterized.py
- [x] tests/cupy_tests/testing_tests/test_condition.py

- [x] tests/cupy_tests/io_tests/test_formatting.py
- [x] tests/cupy_tests/io_tests/test_base_n.py
- [x] tests/cupy_tests/io_tests/test_npz.py
- [x] tests/cupy_tests/io_tests/test_text.py

- [x] tests/cupy_tests/padding_tests/test_pad.py

- [x] tests/cupy_tests/misc_tests/test_who.py
- [x] tests/cupy_tests/misc_tests/test_byte_bounds.py
- [x] tests/cupy_tests/misc_tests/test_memory_ranges.py

- [x] tests/cupy_tests/prof_tests/test_range.py

- [-] tests/cupy_tests/functional_tests/test_vectorize.py
      1 float16 error
- [x] tests/cupy_tests/functional_tests/test_piecewise.py

- [x] tests/cupy_tests/statistics_tests/test_correlation.py
- [x] tests/cupy_tests/statistics_tests/test_order.py
- [x] tests/cupy_tests/statistics_tests/test_meanvar.py
- [-] tests/cupy_tests/statistics_tests/test_histogram.py
      1 float16 error, skip 2D and DD tests for now

- [x] tests/cupy_tests/sorting_tests/test_count.py
- [-] tests/cupy_tests/sorting_tests/test_sort.py
      28 float16 fails
- [-] tests/cupy_tests/sorting_tests/test_search.py
      2 OOMs in TestSearch::test_arg{min,max}_int32_overflow

- [x] tests/cupy_tests/binary_tests/test_packing.py
- [x] tests/cupy_tests/binary_tests/test_elementwise.py

- [x] tests/cupy_tests/cuda_tests/test_driver.py
- [x] tests/cupy_tests/cuda_tests/test_memory.py
- [x] tests/cupy_tests/cuda_tests/test_cutensor.py
- [x] tests/cupy_tests/cuda_tests/test_nvtx.py
- [x] tests/cupy_tests/cuda_tests/test_memory_hook.py
- [x] tests/cupy_tests/cuda_tests/test_graph.py
- [x] tests/cupy_tests/cuda_tests/test_device.py
- [x] tests/cupy_tests/cuda_tests/test_runtime.py
- [x] tests/cupy_tests/cuda_tests/test_pinned_memory.py
- [x] tests/cupy_tests/cuda_tests/test_profile.py
- [x] tests/cupy_tests/cuda_tests/test_nccl.py
- [x] tests/cupy_tests/cuda_tests/test_cufft.py
- [x] tests/cupy_tests/cuda_tests/test_nvrtc.py
- [x] tests/cupy_tests/cuda_tests/test_cudnn.py
- [x] tests/cupy_tests/cuda_tests/test_cusparse.py
- [x] tests/cupy_tests/cuda_tests/test_compiler.py
- [x] tests/cupy_tests/cuda_tests/test_stream.py
- [x] tests/cupy_tests/cuda_tests/test_cublas.py
- [x] tests/cupy_tests/cuda_tests/test_cusolver.py
- [x] tests/cupy_tests/cuda_tests/test_texture.py
- [x] tests/cupy_tests/cuda_tests/test_curand.py
- [x] tests/cupy_tests/cuda_tests/memory_hooks_tests/test_debug_print.py
- [x] tests/cupy_tests/cuda_tests/memory_hooks_tests/test_line_profile.py

- [x] tests/cupy_tests/creation_tests/test_ranges.py
- [x] tests/cupy_tests/creation_tests/test_basic.py
- [x] tests/cupy_tests/creation_tests/test_from_data.py
- [x] tests/cupy_tests/creation_tests/test_matrix.py

- [x] tests/cupy_tests/polynomial_tests/test_polyutils.py
- [x] tests/cupy_tests/polynomial_tests/test_polynomial.py

- [-] tests/cupy_tests/linalg_tests/test_product.py
      27 float16 fails
- [x] tests/cupy_tests/linalg_tests/test_eigenvalue.py
- [x] tests/cupy_tests/linalg_tests/test_norms.py
- [x] tests/cupy_tests/linalg_tests/test_einsum.py
- [x] tests/cupy_tests/linalg_tests/test_decomposition.py
- [x] tests/cupy_tests/linalg_tests/test_solve.py

- [x] tests/cupy_tests/indexing_tests/test_insert.py
- [x] tests/cupy_tests/indexing_tests/test_iterate.py
- [x] tests/cupy_tests/indexing_tests/test_generate.py
- [x] tests/cupy_tests/indexing_tests/test_indexing.py

- [ ] tests/cupy_tests/array_api_tests/test_elementwise_functions.py
- [ ] tests/cupy_tests/array_api_tests/test_validation.py
- [ ] tests/cupy_tests/array_api_tests/test_data_type_functions.py
- [ ] tests/cupy_tests/array_api_tests/test_array_object.py
- [ ] tests/cupy_tests/array_api_tests/test_sorting_functions.py
- [ ] tests/cupy_tests/array_api_tests/test_creation_functions.py
- [ ] tests/cupy_tests/array_api_tests/test_set_functions.py
- [ ] tests/cupy_tests/array_api_tests/test_indexing_functions.py

@kmaehashi
Copy link
Member

Thank you for tackling this, @ev-br! As for OOMs, I'd suggest excluding slow-labeled tests (pytest -m 'not slow') during development. They are for testing functionality against huge ndarray and I think they are safely ignored when working on type promotional rules.

Copy link
Contributor

@seberg seberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for starting this @ev-br! Sorry about the slower followup on our discussions.
This is nicer and really quite minimal, and I think we can make it even more minimal!

As said below, I think passing the weak tuple is probably the pragmatic solution right now and may well be the best solution in the long run also.

A few notes (some of which are inline):

  • It might be nice to have at least a single per-ufunc/kernel "promotion" step. I.e. a custom guess_loop. That would solve many issues, because you could call np.ufunc.resolve_dtypes(). I will note that this function is currently slow and also is only available since 1.24 or so.
  • I have suggested some simplifications, which I think should make things even shorter (I may be missing reasons for why not though).
  • In NumPy I had to add some "very special" paths unfortunately. I think it makes sense to skip that for this PR. However, it would probably make sense to at least for uint_array > -1 add a special path to make it work.
    (i.e. if it is tricky to do for the comparison ufuncs, make it work for the comparisons. For NumPy downstream testing code ran into it often enough and it is somewhat surprising to fail...)

cupy/_core/_reduction.pyx Show resolved Hide resolved
cupy/linalg/_einsum.py Show resolved Hide resolved
@@ -114,7 +114,7 @@ class TestRandintDtype(unittest.TestCase):
def test_dtype(self, dtype):
size = (1000,)
low = numpy.iinfo(dtype).min
high = numpy.iinfo(dtype).max + 1
high = numpy.iinfo(dtype).max
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, this change the test, Maybe need at least a new xfail here since that should work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Have to xfail for numpy 1.26 + remove short ufunc loops here as well:
7217c8d

for a in in_args])
in_types = tuple([a.dtype.type for a in in_args])

op = cache.get((in_types, weaks), ())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, I suspect one could use in_types[weak_pos] = int or so also here, but I think using the weak tuple works well for starters.
(I might want to push for a cleanup after/with my other PR, but this is more urgent.)

cdef _Ops ops_
if dtype is None:
use_raw_value = _check_should_use_min_scalar(in_args)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for me to decide. If we wish to support both 1.x and 2.x (for the most part), it could make sense to keep the _check_should_use_min_scalars here.

As a very subtle point, NumPy still (usually) uses the same check as in if all(weak): weak = [False] * len(weak).

(Which is arguably annoying, and only has an effect for weird integer inputs, though, so I think it is OK to ignore it.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for me to decide either. This PR so far labored under assumption that cupy 14 only supports numpy 2.0, per #8306 (comment).
BTW, this implies that cupyx.scipy requires scipy 1.13


if not ok:
raise OverflowError(f"Python integer {arg} out of "
f"bounds for {out_type}.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a lot of code that really ends up doing the same as: out_type(int(arg)) or out_type(arg.item())?
I suppose one could check safe-cast first, although I am not sure it would be faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean, mind expanding? This code is meant to check iinfo.min <= arg <= iinfo.max where arg can be signed or unsigned. Cython is trying to be helpful, so need explicit casts to avoid overflows.

Copy link
Contributor

@seberg seberg May 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is, write this whole thing as:

for in_type, arg, weak for zip(in_types, in_args, weaks):
    if not weak is not int:  # assume we change what is stored in `weaks`
        continue

    in_type(int(in_arg))  # check if Python integer fits

(Or something similar of course, not sure that the zip is great if we micro-optimize.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now that I look again, I think it also needs to loop in_types and not rely on out_type being identical.

if not can_cast(it[0], ot) and not can_cast(it[1], ot):
break
elif not can_cast(it, ot):
elif not is_weak and not can_cast(it, ot):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it is a bit slow, but it should be cached, so I would suggest replacing the full above logic logic with:

try:
    safe = np.result_type(weak(0), ot) == ot
except TypeError:
    safe = False

Might not be the prettiest ever, but I think it is preferable to custom implementation of the category logic and more flexible for future additions.

I am suggesting another trick: Let's make weaks = [False, int, float, complex] i.e. store either False or the type, so that we can use the type information directly from there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, in_types entries are numpy scalars types already, after the call to

cdef inline _preprocess_arg(int dev_id, arg, bint use_c_scalar):
at
in_args, weaks = _preprocess_args(dev_id, in_args, False)

Which is the main reason to have an additional weaks tuple to be able to distinguish int8(1) + 1 from int8(1) + int8(1).

So your suggestion is to keep python types to be python types all the way instead of converting them to numpy types early on?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That could be nice, but probably comes with it's downsides. I was suggestion to make the weaks tuple contain one of False/int/float/complex rather than just True/False. That gives you the information which original type you were dealing with without using issubdtype or so.

('bb->d', 'BB->d', 'hh->d', 'HH->d', 'ii->d', 'II->d', 'll->d', 'LL->d',
'qq->d', 'QQ->d', 'ee->e', 'ff->f', 'dd->d', 'FF->F', 'DD->D'),
'out0 = (out0_type)in0 / (out0_type)in1',
('qq->d', 'QQ->d',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, this has a slight miss for mixed signs, but that seems OK.

In principle it would be nice to solve this with a custom promotion step for the ufunc. This could be very nice, because for (almost!) all NumPy ufunc, we should be able to at least try and use:

dtypes = ufunc.resolve_dtypes()

@ev-br ev-br force-pushed the nep50 branch 2 times, most recently from f08268b to 60a80c3 Compare May 18, 2024 11:12
@ev-br
Copy link
Contributor Author

ev-br commented May 19, 2024

Progress: @fuse reuses the ufunc machinery for type promotion. core_tests/fusion_tests all pass, at least locally.

@ev-br
Copy link
Contributor Author

ev-br commented May 20, 2024

Status:

  • locally,$ for f in `ls tests/cupy_tests; do echo $f && pytest tests/cupy_tests/$f -n 8 -m'not slow' --tb=no; done all passes modulo two OOMs in test_numpy_interop. OOMs are likely irrelevant for the promotion state changes;
  • @seberg's comments are all addressed --- mostly by Sebastian himself, his commits are included into the PR;
  • there are several skips/xfails for things which are broken in numpy 1.26.x + weak promotion and are fixed in numpy 2.0.0rc2;
  • there might be more issues in the cupyx namespace, but then it also depends on e.g. the scipy version;
  • there's a question on how to enable this, also in relation to WIP: support NumPy 2.0 : NEP 52 (Python API cleanup) #8314:
    • do we want to push this PR to be CI green (then how to add export NPY_PROMOTION_STATE=weak on CI?) , then work on NumPy 2.0 API changes separately, or
    • can we tolerate some CI failures while this is in flux, or
    • do we lump these two PRs together.

Copy link
Contributor

@seberg seberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my perspective, I think the logic here should be big enough step forward that it would be great to push it forward/merge soon.

The main issue (as @ev-br said) seems now to ensure that tests pass for developers and CI. What we need for that may be:

  • Force testing with NumPy 1.26 and NPY_PROMOTION_STATE="weak". We can do that in conftest.py.
  • Fixing CI! Unfortunately, I am not sure what is all needed for that. I would think that could be split out in a separate PR.

Otherwise, I think it should be at most be small fixups (a few new xfails, and maybe making sure all xfails/odd or temporary paths are easy to grep for).

There are some more complicated issues, however, I think it is probably better to defer them:

  • Many current xfails actually work in NumPy 2 (should we use a skipif?)
  • NumPy 2 has some special logic to e.g. make uint_arr > -1 work.
    (I am not sure how vital this is, but to fix it we will have to add a distinct layer of logic and that seems better in a new PR with an issue.)

The goal here is currently to create a CuPy v14 that matches NumPy 2, but fails to match NumPy 1.x w.r.t. to promotion.
That means users will have to stay with CuPy v13 if they have NumPy 1.x (and need it to match).
I think this aligns with the current plans of the CuPy team, but I am not sure.

I will note that I am sure we could implement both versions side-by-side without too much hassle and I would be happy to do this if it seems helpful/desirable (even if it is just helpful with getting CI going).

cupy/_core/fusion.pyx Outdated Show resolved Hide resolved
tests/cupyx_tests/jit_tests/test_cooperative_groups.py Outdated Show resolved Hide resolved
@ev-br
Copy link
Contributor Author

ev-br commented May 22, 2024

With a slew of fixups/skips/xfails in the cupyx namespace, this is ready from my side.

seberg added a commit to seberg/cupy-feedstock that referenced this pull request May 23, 2024
This (tries to) build artifacts based on Evgeni's PR to CuPy which should
have most fixes needed to run with NumPy 2 and thus allow testing downstream
projects with NumPy 2 if they also need CuPy.

This includes most/all necessary Python fixes as well as fixes to make
promotion align with NumPy (NEP 50).

See also:
* cupy/cupy#8323
* cupy/cupy#8314
* cupy/cupy#8306
ev-br added 8 commits May 23, 2024 16:44
These tests fail with "arrays of different dtypes are returned" on
NumPy 1.26.4 with weak promotion (export NPY_PROMOTION_STATE=weak),
but pass under NumPy '2.1.0.dev0+git20240419.da95f8e'.

Therefore, this commit can be reverted when NumPy 2.0 becomes the
minimum supported version.
The NumPy < 2 idiom,
int( np.array(seed).astype(np.uint64, casting='safe') )
does not work in NumPy 2.0
Test that either both NumPy and CuPy raise OverflowErrors,
or both do not.
Otherwise, `arange(3, dtype=cupy.uint8).round(-2)` raises: `-2` cannot be cast
to the array unsigned dtype.
ev-br and others added 28 commits May 23, 2024 16:44
SciPy does not emit a warning anymore? Retry with NumPy 2.0 proper.
cannot have short int/uint loops:
>>> arange(3, dtype'int8') < 200

should convert both operands to int64/uint64
Reuse the type promotion logic from ufuncs.
Co-authored-by: Sebastian Berg <sebastian@sipsolutions.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cat:numpy-compat Follow the NumPy/SciPy spec changes prio:medium
Projects
Status: 🏭 In progress
Development

Successfully merging this pull request may close these issues.

None yet

6 participants