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

fix: ListArray slicing on GPU #3248

Merged
merged 20 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion dev/generate-kernel-signatures.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,10 @@ def by_signature(cuda_kernel_templates):
special = [repr(spec["name"])]
[type_to_pytype(x["type"], special) for x in childfunc["args"]]
dirlist = [repr(x["dir"]) for x in childfunc["args"]]
ispointerlist = [repr("List" in x["type"]) for x in childfunc["args"]]
ispointerlist = [
repr("List" in x["type"] or "ListArray-at" == x.get("role", None))
ianna marked this conversation as resolved.
Show resolved Hide resolved
for x in childfunc["args"]
]
if spec["name"] in cuda_kernels_impl:
with open(
os.path.join(
Expand Down
6 changes: 3 additions & 3 deletions kernel-specification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1466,7 +1466,7 @@ kernels:
- {name: tocarry, type: "List[int64_t]", dir: out}
- {name: fromstarts, type: "Const[List[int32_t]]", dir: in, role: ListArray-starts}
- {name: fromstops, type: "Const[List[int32_t]]", dir: in, role: ListArray-stops}
- {name: jaggedsize, type: "int64_t", dir: in, role: ListArray-at}
- {name: jaggedsize, type: "int64_t", dir: in, role: ListArray-length}
- {name: length, type: "int64_t", dir: in, role: default}
- name: awkward_ListArray64_getitem_jagged_expand_64
args:
Expand All @@ -1476,7 +1476,7 @@ kernels:
- {name: tocarry, type: "List[int64_t]", dir: out}
- {name: fromstarts, type: "Const[List[int64_t]]", dir: in, role: ListArray-starts}
- {name: fromstops, type: "Const[List[int64_t]]", dir: in, role: ListArray-stops}
- {name: jaggedsize, type: "int64_t", dir: in, role: ListArray-at}
- {name: jaggedsize, type: "int64_t", dir: in, role: ListArray-length}
- {name: length, type: "int64_t", dir: in, role: default}
- name: awkward_ListArrayU32_getitem_jagged_expand_64
args:
Expand All @@ -1486,7 +1486,7 @@ kernels:
- {name: tocarry, type: "List[int64_t]", dir: out}
- {name: fromstarts, type: "Const[List[uint32_t]]", dir: in, role: ListArray-starts}
- {name: fromstops, type: "Const[List[uint32_t]]", dir: in, role: ListArray-stops}
- {name: jaggedsize, type: "int64_t", dir: in, role: ListArray-at}
- {name: jaggedsize, type: "int64_t", dir: in, role: ListArray-length}
- {name: length, type: "int64_t", dir: in, role: default}
description: null
definition: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ awkward_ListArray_getitem_next_at(
const C* fromstarts,
const U* fromstops,
int64_t lenstarts,
int64_t at,
int64_t* at,
uint64_t invocation_index,
uint64_t* err_code) {
if (err_code[0] == NO_ERROR) {
int64_t thread_id = blockIdx.x * blockDim.x + threadIdx.x;

if (thread_id < lenstarts) {
int64_t length = fromstops[thread_id] - fromstarts[thread_id];
int64_t regular_at = at;
int64_t regular_at = at[0];
if (regular_at < 0) {
regular_at += length;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ template <typename T>
__global__ void
awkward_RegularArray_getitem_next_at(
T* tocarry,
int64_t at,
int64_t* at,
int64_t length,
int64_t size,
uint64_t invocation_index,
uint64_t* err_code) {
if (err_code[0] == NO_ERROR) {
int64_t thread_id = blockIdx.x * blockDim.x + threadIdx.x;
int64_t regular_at = at;
int64_t regular_at = at[0];
if (regular_at < 0) {
regular_at += size;
}
Expand Down
1 change: 1 addition & 0 deletions src/awkward/contents/listarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,7 @@ def _getitem_next(
nexthead, nexttail = ak._slicing.head_tail(tail)
lenstarts = self._starts.length
nextcarry = ak.index.Index64.empty(lenstarts, self._backend.index_nplike)
head = ak._slicing.normalize_integer_like(head)
assert (
nextcarry.nplike is self._backend.index_nplike
and self._starts.nplike is self._backend.index_nplike
Expand Down
3 changes: 1 addition & 2 deletions src/awkward/contents/regulararray.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,7 @@ def _getitem_next(
nexthead, nexttail = ak._slicing.head_tail(tail)
nextcarry = ak.index.Index64.empty(self._length, index_nplike)
assert nextcarry.nplike is index_nplike
if ak.backend(head) == "cuda":
head = int(ak.to_backend(head, backend=self._backend)[0])
head = ak._slicing.normalize_integer_like(head)
jpivarski marked this conversation as resolved.
Show resolved Hide resolved
self._maybe_index_error(
self._backend[
"awkward_RegularArray_getitem_next_at", nextcarry.dtype.type
Expand Down
120 changes: 120 additions & 0 deletions tests-cuda/test_3140_cuda_slicing.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,3 +677,123 @@ def test_0127_tomask_operation():
[None],
[6.6, None, None, 9.9],
]


def test_simple_slice_cpu():
arr = ak.Array([[1, 2, 3], [0], [4, 5]])
out = arr[:, 0]
expected = [1, 0, 4]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)


def test_simple_slice_gpu():
arr = ak.Array([[1, 2, 3], [0], [4, 5]], backend="cuda")
out = arr[:, 0]
expected = [1, 0, 4]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)


def test_simple_slice_cpu1():
arr = ak.Array([[1, 2, 3], [0], [4, 5]])
out = arr[:, 1:]
expected = [[2, 3], [], [5]]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)


def test_simple_slice_gpu1():
arr = ak.Array([[1, 2, 3], [0], [4, 5]], backend="cuda")
out = arr[:, 1:]
expected = [[2, 3], [], [5]]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)


def test_simple_slice_cpu2():
arr = ak.Array([[1, 2, 3], [0], [4, 5]])
out = arr[:, :1]
expected = [[1], [0], [4]]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)


def test_simple_slice_gpu2():
arr = ak.Array([[1, 2, 3], [0], [4, 5]], backend="cuda")
out = arr[:, :1]
expected = [[1], [0], [4]]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)


def test_simple_slice_cpu3():
arr = ak.Array([[1, 2, 3], [0], [4, 5]])
out = arr[:, 1::2]
expected = [[2], [], [5]]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)


def test_simple_slice_gpu3():
arr = ak.Array([[1, 2, 3], [0], [4, 5]], backend="cuda")
out = arr[:, 1::2]
expected = [[2], [], [5]]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)


def test_simple_slice_cpu4():
arr = ak.Array([[1, 2, 3], [0], [4, 5]])
out = arr[:, ::-1]
expected = [[3, 2, 1], [0], [5, 4]]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)


def test_simple_slice_gpu4():
arr = ak.Array([[1, 2, 3], [0], [4, 5]], backend="cuda")
out = arr[:, ::-1]
expected = [[3, 2, 1], [0], [5, 4]]
result = out.tolist()
cp.testing.assert_array_list_equal(
result,
expected,
err_msg=f"Slice of [[1, 2, 3], [0], [4, 5]] should be {expected}, but got {result}",
)
Loading