Skip to content

Commit a3269fe

Browse files
authored
Merge pull request #115 from shreyas-omkar/sh/findall
feat(findall): Add findall kernel
2 parents 5b253ab + c50badf commit a3269fe

7 files changed

Lines changed: 534 additions & 40 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ If you need other algorithms in your work that may be of general use, please ope
281281
| [Accumulation](https://juliagpu.github.io/AcceleratedKernels.jl/stable/api/accumulate/) | `accumulate` `accumulate!` | `prefix_sum` `thrust::scan` `cumsum` |
282282
| [Binary Search](https://juliagpu.github.io/AcceleratedKernels.jl/stable/api/binarysearch/) | `searchsortedfirst` `searchsortedfirst!` | `std::lower_bound` |
283283
| | `searchsortedlast` `searchsortedlast!` | `thrust::upper_bound` |
284+
| [Find All](https://juliagpu.github.io/AcceleratedKernels.jl/stable/api/findall/) | `findall` | `thrust::copy_if` `cub::DeviceSelect` `nonzero` |
284285
| [Predicates](https://juliagpu.github.io/AcceleratedKernels.jl/stable/api/predicates/) | `all` `any` | |
285286
| [Arithmetics](https://juliagpu.github.io/AcceleratedKernels.jl/stable/api/arithmetics/) | `sum` `prod` `minimum` `maximum` `count` `cumsum` `cumprod` | |
286287

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ makedocs(;
2828
"MapReduce" => "api/mapreduce.md",
2929
"Accumulate" => "api/accumulate.md",
3030
"Binary Search" => "api/binarysearch.md",
31+
"Find All" => "api/findall.md",
3132
"Predicates" => "api/predicates.md",
3233
"Arithmetics" => "api/arithmetics.md",
3334
"Custom Structs" => "api/custom_structs.md",

docs/src/api/findall.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
### Find All / Stream Compaction
2+
3+
```@docs
4+
AcceleratedKernels.findall
5+
AcceleratedKernels.ScanScatter
6+
```

src/AcceleratedKernels.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ include("map.jl")
3232
include("sort/sort.jl")
3333
include("reduce/reduce.jl")
3434
include("accumulate/accumulate.jl")
35+
include("findall.jl")
3536
include("reverse.jl")
3637
include("searchsorted.jl")
3738
include("predicates.jl")

src/accumulate/accumulate_1d_gpu.jl

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,49 @@ end
1515
function _decoupled_fence end
1616

1717

18+
# Exclusive scan of one value per thread in local memory. All threads in the block must call it.
19+
@inline function block_exclusive_scan!(@context, op, totals, seed, block_size, ithread)
20+
# Up-sweep. Use index-sized counters for block sizes of 256 or more.
21+
offset = one(ithread)
22+
d = block_size >> 0x1
23+
while d > 0x0
24+
@synchronize()
25+
if ithread < d
26+
ai = offset * (0x2 * ithread + 0x1) - 0x1
27+
bi = offset * (0x2 * ithread + 0x2) - 0x1
28+
totals[bi + 0x1] = op(totals[bi + 0x1], totals[ai + 0x1])
29+
end
30+
offset = offset << 0x1
31+
d = d >> 0x1
32+
end
33+
34+
@synchronize()
35+
block_total = op(seed, totals[block_size])
36+
@synchronize()
37+
if ithread == 0x0
38+
totals[block_size] = seed
39+
end
40+
41+
# Down-sweep to an exclusive scan.
42+
d = one(ithread)
43+
while d < block_size
44+
offset = offset >> 0x1
45+
@synchronize()
46+
if ithread < d
47+
ai = offset * (0x2 * ithread + 0x1) - 0x1
48+
bi = offset * (0x2 * ithread + 0x2) - 0x1
49+
t = totals[ai + 0x1]
50+
totals[ai + 0x1] = totals[bi + 0x1]
51+
totals[bi + 0x1] = op(totals[bi + 0x1], t)
52+
end
53+
d = d << 0x1
54+
end
55+
@synchronize()
56+
57+
return totals[ithread + 0x1], block_total
58+
end
59+
60+
1861
# Register-raking block scan with striped loads and stores.
1962
@kernel cpu=false inbounds=true unsafe_indices=true function _accumulate_block!(
2063
op, v, init, neutral,
@@ -53,50 +96,13 @@ function _decoupled_fence end
5396
k += 1
5497
end
5598
thread_totals[ithread + 0x1] = acc
56-
@synchronize()
5799

58100
# Scan the per-thread totals. Later blocks receive their carry from the
59101
# second kernel.
60102
seed = iblock == 0x0 ? init : neutral
61-
62-
# Use index-sized counters for block sizes of 256 or more.
63-
offset = one(ithread)
64-
d = block_size >> 0x1
65-
while d > 0x0
66-
@synchronize()
67-
if ithread < d
68-
ai = offset * (0x2 * ithread + 0x1) - 0x1
69-
bi = offset * (0x2 * ithread + 0x2) - 0x1
70-
thread_totals[bi + 0x1] =
71-
op(thread_totals[bi + 0x1], thread_totals[ai + 0x1])
72-
end
73-
offset = offset << 0x1
74-
d = d >> 0x1
75-
end
76-
77-
@synchronize()
78-
block_total = op(seed, thread_totals[block_size])
79-
@synchronize()
80-
if ithread == 0x0
81-
thread_totals[block_size] = seed
82-
end
83-
84-
# Down-sweep to an exclusive scan.
85-
d = one(ithread)
86-
while d < block_size
87-
offset = offset >> 0x1
88-
@synchronize()
89-
if ithread < d
90-
ai = offset * (0x2 * ithread + 0x1) - 0x1
91-
bi = offset * (0x2 * ithread + 0x2) - 0x1
92-
t = thread_totals[ai + 0x1]
93-
thread_totals[ai + 0x1] = thread_totals[bi + 0x1]
94-
thread_totals[bi + 0x1] = op(thread_totals[bi + 0x1], t)
95-
end
96-
d = d << 0x1
97-
end
98-
@synchronize()
99-
thread_prefix = thread_totals[ithread + 0x1]
103+
thread_prefix, block_total = block_exclusive_scan!(
104+
@context, op, thread_totals, seed, block_size, ithread,
105+
)
100106

101107
# DecoupledLookback keeps later blocks inclusive until the carry pass.
102108
block_inclusive = inclusive || (iblock != 0x0 && !isnothing(flags))

0 commit comments

Comments
 (0)