Skip to content

Fix abort on empty boolean-mask advanced indexing - #3019

Merged
antonwolfy merged 3 commits into
masterfrom
fix-empty-boolean-adv-indexing
Aug 14, 2026
Merged

Fix abort on empty boolean-mask advanced indexing#3019
antonwolfy merged 3 commits into
masterfrom
fix-empty-boolean-adv-indexing

Conversation

@antonwolfy

@antonwolfy antonwolfy commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Boolean-mask advanced indexing (dpnp.ndarray.__getitem__/__setitem__) aborted when the selection was empty. For example:

import dpnp
a = dpnp.zeros((2, 3, 4))
a[False, [True, False]] = 1   # scalar `False` injects a length-0 axis

py_place and py_extract compute the orthogonal and masked element counts and dispatch to the strided masked place/extract kernels without checking for zero. When the boolean index produces an empty selection — e.g. a leading scalar False that injects a length-0 axis — ortho_nelems becomes 0, and the some-slices kernel builds sycl::nd_range<2> with GlobalSize[0] == 0 and a non-zero local size.

That is a degenerate launch. It is a silent no-op on a SYCL runtime built with NDEBUG, so it goes unnoticed with the released oneAPI runtime. On an assertions-enabled SYCL runtime it aborts, because adjustNDRangePerKernel asserts NDR.LocalSize[0] == 0 whenever GlobalSize[0] is 0:

Assertion `NDR.LocalSize[0] == 0' failed.
  .../sycl/source/detail/scheduler/commands.cpp
  void sycl::_V1::detail::adjustNDRangePerKernel(...)

This PR proposes to return early with empty events when the orthogonal or masked element count is zero, before any kernel is submitted, in both py_place and py_extract. An empty selection is a no-op, so this is semantically correct and mirrors the existing cumsum_sz == 0 guard in the same file.

Note, the issue was identified when building with the nightly LLVM SYCL compiler and running dpnp tests.
And the test is passing with the fix:

dpnp/tests/third_party/cupy/core_tests/test_ndarray_adv_indexing.py::TestArrayAdvancedIndexingSetitemScalarValue::test_adv_setitem[42] PASSED [ 77%]

  • Have you provided a meaningful PR description?
  • Have you added a test, reproducer or referred to an issue with a reproducer?
  • Have you tested your changes locally for CPU and GPU devices?
  • Have you made sure that new changes do not introduce compiler warnings?
  • Have you checked performance impact of proposed changes?
  • Have you added documentation for your changes, if necessary?
  • Have you added your changes to the changelog?

py_place and py_extract computed the orthogonal and masked element counts
and dispatched to the strided kernels without checking for zero. When a
boolean index produces an empty selection - e.g. a leading scalar `False`
that injects a length-0 axis - ortho_nelems becomes 0, and the some-slices
kernel builds sycl::nd_range<2> with GlobalSize[0] == 0 and a non-zero
local size. That is a degenerate launch: it is a silent no-op on runtimes
built with NDEBUG, but aborts on an assertions-enabled SYCL runtime
(adjustNDRangePerKernel asserts NDR.LocalSize[0] == 0 when GlobalSize is 0).

Return early with empty events when ortho_nelems or the masked element
count is zero, so no kernel is submitted for an empty selection.
@antonwolfy antonwolfy added this to the 0.21.0 release milestone Aug 12, 2026
@antonwolfy antonwolfy self-assigned this Aug 12, 2026
@github-actions

Copy link
Copy Markdown
Contributor

View rendered docs @ https://intelpython.github.io/dpnp/pull/3019/index.html

@antonwolfy
antonwolfy marked this pull request as ready for review August 12, 2026 10:54
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Array API standard conformance tests for dpnp=0.21.0dev4=py314h509198e_7 ran successfully.
Passed: 1376
Failed: 1
Skipped: 5

@coveralls

coveralls commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Coverage Status

No base build to compare — fix-empty-boolean-adv-indexing into master

@ndgrigorian ndgrigorian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@antonwolfy
antonwolfy merged commit 12b436f into master Aug 14, 2026
96 of 102 checks passed
@antonwolfy
antonwolfy deleted the fix-empty-boolean-adv-indexing branch August 14, 2026 14:11
github-actions Bot added a commit that referenced this pull request Aug 14, 2026
Boolean-mask advanced indexing
(`dpnp.ndarray.__getitem__`/`__setitem__`) aborted when the selection
was empty. For example:

```python
import dpnp
a = dpnp.zeros((2, 3, 4))
a[False, [True, False]] = 1   # scalar `False` injects a length-0 axis
```

`py_place` and `py_extract` compute the orthogonal and masked element
counts and dispatch to the strided masked place/extract kernels without
checking for zero. When the boolean index produces an empty selection —
e.g. a leading scalar `False` that injects a length-0 axis —
`ortho_nelems` becomes `0`, and the some-slices kernel builds
`sycl::nd_range<2>` with `GlobalSize[0] == 0` and a non-zero local size.

That is a degenerate launch. It is a silent no-op on a SYCL runtime
built with `NDEBUG`, so it goes unnoticed with the released oneAPI
runtime. On an assertions-enabled SYCL runtime it aborts, because
`adjustNDRangePerKernel` asserts `NDR.LocalSize[0] == 0` whenever
`GlobalSize[0]` is `0`:

```
Assertion `NDR.LocalSize[0] == 0' failed.
  .../sycl/source/detail/scheduler/commands.cpp
  void sycl::_V1::detail::adjustNDRangePerKernel(...)
```

This PR proposes to return early with empty events when the orthogonal
or masked element count is zero, before any kernel is submitted, in both
`py_place` and `py_extract`. An empty selection is a no-op, so this is
semantically correct and mirrors the existing `cumsum_sz == 0` guard in
the same file.

Note, the issue was identified when building with the nightly LLVM SYCL
compiler and
[running](https://github.com/antonwolfy/dpnp/actions/runs/31576568012/job/94049919151)
dpnp tests.
And the test is
[passing](https://github.com/antonwolfy/dpnp/actions/runs/31585418522/job/94078011200)
with the fix:
>
dpnp/tests/third_party/cupy/core_tests/test_ndarray_adv_indexing.py::TestArrayAdvancedIndexingSetitemScalarValue::test_adv_setitem[42]
PASSED [ 77%] 12b436f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants