Skip to content

Commit efdc7cf

Browse files
Implement issorted for AbstractGPUArray without scalar indexing. (#678)
1 parent f516fc2 commit efdc7cf

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

src/host/base.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,47 @@
11
# common Base functionality
22
import Base: _RepeatInnerOuter
33

4+
@kernel function issorted_kernel!(
5+
data,
6+
violations,
7+
ord,
8+
)
9+
i = @index(Global)
10+
if i <= length(violations)
11+
@inbounds begin
12+
a = data[i]
13+
b = data[i + 1]
14+
violations[i] = Base.Order.lt(ord, b, a)
15+
end
16+
end
17+
end
18+
19+
function Base.issorted(A::AbstractGPUArray; lt::Function = isless, by::Function = identity, rev::Bool = false, order = Base.Order.Forward)
20+
if order === Base.Order.Reverse
21+
rev = !rev
22+
order = Base.Order.Forward
23+
elseif order !== Base.Order.Forward
24+
throw(ArgumentError("custom orderings are not supported on GPU"))
25+
end
26+
27+
n = length(A)
28+
n 1 && return true
29+
30+
ord = Base.Order.ord(lt, by, rev, order)
31+
32+
violations = similar(A, Bool, n - 1)
33+
backend = get_backend(A)
34+
35+
issorted_kernel!(backend)(
36+
A,
37+
violations,
38+
ord,
39+
ndrange = n - 1,
40+
)
41+
42+
return !any(Array(violations))
43+
end
44+
445
# Handle `out = repeat(x; inner)` by parallelizing over `out` array This can benchmark
546
# faster if repeating elements along the first axis (i.e. `inner=(n, ones...)`), as data
647
# access can be contiguous on write.

test/testsuite/base.jl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,50 @@ end
2929
end
3030
end
3131

32+
@testset "issorted" begin
33+
# basic sorted / unsorted
34+
@test compare(issorted, AT, [1, 2, 3, 4])
35+
@test compare(x -> !issorted(x), AT, [1, 3, 2, 4])
36+
37+
# reverse ordering
38+
@test compare(x -> issorted(x; rev = true), AT, [4, 3, 2, 1])
39+
@test compare(x -> !issorted(x; rev = true), AT, [1, 2, 3])
40+
41+
# custom lt
42+
@test compare(x -> issorted(x; lt = >), AT, [3, 2, 1])
43+
@test compare(x -> !issorted(x; lt = >), AT, [1, 2, 3])
44+
45+
# by = abs
46+
@test compare(x -> issorted(x; by = abs), AT, [-1, -2, -3])
47+
@test compare(x -> !issorted(x; by = abs), AT, [-1, -3, -2])
48+
49+
# order keyword normalization
50+
@test compare(
51+
x -> issorted(x; order = Base.Order.Reverse),
52+
AT,
53+
[3, 2, 1],
54+
)
55+
56+
@test compare(
57+
x -> !issorted(x; order = Base.Order.Reverse),
58+
AT,
59+
[1, 2, 3],
60+
)
61+
62+
# edge cases
63+
@test compare(issorted, AT, Int[])
64+
@test compare(issorted, AT, [42])
65+
66+
# unsupported custom orderings
67+
AT <: AbstractGPUArray && @testset "unsupported orderings" begin
68+
x = AT([1, 2, 3])
69+
@test_throws ArgumentError issorted(
70+
x;
71+
order = Base.Order.By(identity),
72+
)
73+
end
74+
end
75+
3276
@testset "copy!" begin
3377
for (dst, src,) in (
3478
(rand(Float32, (10,)), rand(Float32, (10,))), # vectors

0 commit comments

Comments
 (0)