-
Notifications
You must be signed in to change notification settings - Fork 195
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
support for active_cells_map in kernels #3920
base: main
Are you sure you want to change the base?
Changes from 10 commits
279e4c4
6182e34
5545605
e239dbe
32e0c52
0b56304
052f56e
d0d56ac
7e41737
42d4989
130a357
3be13dd
64cad18
333bfd7
e069051
f0a887a
7b33e7a
26194f3
db84ef2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -6,7 +6,9 @@ using Oceananigans: location | |||||
using Oceananigans.Architectures | ||||||
using Oceananigans.Grids | ||||||
using Oceananigans.Grids: AbstractGrid | ||||||
using Adapt | ||||||
using Base: @pure | ||||||
using KernelAbstractions: Kernel | ||||||
|
||||||
import Oceananigans | ||||||
import KernelAbstractions: get, expand | ||||||
|
@@ -80,6 +82,28 @@ end | |||||
contiguousrange(range::NTuple{N, Int}, offset::NTuple{N, Int}) where N = Tuple(1+o:r+o for (r, o) in zip(range, offset)) | ||||||
flatten_reduced_dimensions(worksize, dims) = Tuple(d ∈ dims ? 1 : worksize[d] for d = 1:3) | ||||||
|
||||||
#### | ||||||
#### Internal utility to launch a function mapped on an index_map | ||||||
#### | ||||||
|
||||||
struct MappedFunction{F, M} <: Function | ||||||
f::F | ||||||
imap::M | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. index_map? |
||||||
end | ||||||
|
||||||
Adapt.adapt_structure(to, m::MappedFunction) = | ||||||
MappedFunction(Adapt.adapt(to, m.f), Adapt.adapt(to, m.imap)) | ||||||
|
||||||
@inline function (m::MappedFunction)(_ctx_) | ||||||
m.f(_ctx_) | ||||||
return nothing | ||||||
end | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isn't this case covered by the case with |
||||||
|
||||||
@inline function (m::MappedFunction)(_ctx_, args...) | ||||||
m.f(_ctx_, args...) | ||||||
return nothing | ||||||
end | ||||||
|
||||||
# Support for 1D | ||||||
heuristic_workgroup(Wx) = min(Wx, 256) | ||||||
|
||||||
|
@@ -238,9 +262,20 @@ the architecture `arch`. | |||||
|
||||||
dev = Architectures.device(arch) | ||||||
loop = kernel!(dev, workgroup, worksize) | ||||||
|
||||||
# Map out the function to use active_cells_map | ||||||
# as an index map | ||||||
if !isnothing(active_cells_map) | ||||||
func = MappedFunction(loop.f, active_cells_map) | ||||||
param = get_kernel_parameters(loop) | ||||||
M = typeof(func) | ||||||
loop = Kernel{param..., M}(dev, func) | ||||||
end | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doesn't it make more sense to put this in the first if-statement in this function? |
||||||
|
||||||
return loop, worksize | ||||||
end | ||||||
|
||||||
@inline get_kernel_parameters(k::Kernel{A, B, C}) where {A, B, C} = A, B, C | ||||||
|
||||||
""" | ||||||
launch!(arch, grid, workspec, kernel!, kernel_args...; kw...) | ||||||
|
@@ -272,10 +307,7 @@ end | |||||
@inline function _launch!(arch, grid, workspec, kernel!, first_kernel_arg, other_kernel_args...; | ||||||
exclude_periphery = false, | ||||||
reduced_dimensions = (), | ||||||
active_cells_map = nothing, | ||||||
# TODO: these two kwargs do nothing: | ||||||
only_local_halos = false, | ||||||
async = false) | ||||||
active_cells_map = nothing) | ||||||
|
||||||
location = Oceananigans.location(first_kernel_arg) | ||||||
|
||||||
|
@@ -320,6 +352,13 @@ using KernelAbstractions: Kernel | |||||
using KernelAbstractions.NDIteration: _Size, StaticSize | ||||||
using KernelAbstractions.NDIteration: NDRange | ||||||
|
||||||
using KernelAbstractions.NDIteration | ||||||
using KernelAbstractions: ndrange, workgroupsize | ||||||
import KernelAbstractions: partition | ||||||
|
||||||
using KernelAbstractions: CompilerMetadata | ||||||
import KernelAbstractions: __ndrange, __groupsize | ||||||
|
||||||
struct OffsetStaticSize{S} <: _Size | ||||||
function OffsetStaticSize{S}() where S | ||||||
new{S::Tuple{Vararg}}() | ||||||
|
@@ -369,13 +408,6 @@ const OffsetNDRange{N} = NDRange{N, <:StaticSize, <:StaticSize, <:Any, <:KernelO | |||||
return CartesianIndex(nI) | ||||||
end | ||||||
|
||||||
using KernelAbstractions.NDIteration | ||||||
using KernelAbstractions: ndrange, workgroupsize | ||||||
import KernelAbstractions: partition | ||||||
|
||||||
using KernelAbstractions: CompilerMetadata | ||||||
import KernelAbstractions: __ndrange, __groupsize | ||||||
|
||||||
@inline __ndrange(::CompilerMetadata{NDRange}) where {NDRange<:OffsetStaticSize} = CartesianIndices(get(NDRange)) | ||||||
@inline __groupsize(cm::CompilerMetadata{NDRange}) where {NDRange<:OffsetStaticSize} = size(__ndrange(cm)) | ||||||
|
||||||
|
@@ -413,3 +445,58 @@ function partition(kernel::OffsetKernel, inrange, ingroupsize) | |||||
return iterspace, dynamic | ||||||
end | ||||||
|
||||||
##### | ||||||
##### Utilities for Mapped kernels | ||||||
##### | ||||||
|
||||||
struct IndexMap{M} | ||||||
imap :: M | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
end | ||||||
|
||||||
Adapt.adapt_structure(to, m::IndexMap) = IndexMap(Adapt.adapt(to, m.index_map)) | ||||||
|
||||||
const MappedNDRange{N} = NDRange{N, <:StaticSize, <:StaticSize, <:Any, <:IndexMap} where N | ||||||
|
||||||
# NDRange has been modified to include an index_map in place of workitems: R | ||||||
# Remember, dynamic offset kernels are not possible with this extension!! | ||||||
# Also, mapped kernels work only with a 1D kernel and a 1D map, it is not possible to launch a ND kernel. | ||||||
# TODO: maybe don't do this | ||||||
@inline function expand(ndrange::MappedNDRange, groupidx::CartesianIndex, idx::CartesianIndex) | ||||||
Base.@_inline_meta | ||||||
offsets = workitems(ndrange) | ||||||
stride = size(offsets, 1) | ||||||
gidx = groupidx.I[1] | ||||||
tI = (gidx - 1) * stride + idx.I[1] | ||||||
nI = ndrange.workitems.imap[tI] | ||||||
return CartesianIndex(nI) | ||||||
end | ||||||
|
||||||
const MappedKernel{D} = Kernel{D, <:Any, <:Any, <:MappedFunction} where D | ||||||
|
||||||
# Override the getproperty to make sure we get the correct properties | ||||||
@inline getproperty(k::MappedKernel, prop::Symbol) = get_mapped_property(k, Val(prop)) | ||||||
|
||||||
@inline get_mapped_property(k, ::Val{:imap}) = k.f.imap | ||||||
@inline get_mapped_property(k, ::Val{:f}) = k.f.f | ||||||
|
||||||
# Extending the partition function to include offsets in NDRange: note that in this case the | ||||||
# offsets take the place of the DynamicWorkitems which we assume is not needed in static kernels | ||||||
function partition(kernel::MappedKernel, inrange, ingroupsize) | ||||||
static_workgroupsize = workgroupsize(kernel) | ||||||
|
||||||
# Calculate the static NDRange and WorkgroupSize | ||||||
index_map = getproperty(kernel, :imap) | ||||||
range = length(index_map) | ||||||
arch = Oceananigans.Architectures.architecture(index_map) | ||||||
groupsize = get(static_workgroupsize) | ||||||
|
||||||
blocks, groupsize, dynamic = NDIteration.partition(range, groupsize) | ||||||
|
||||||
static_blocks = StaticSize{blocks} | ||||||
static_workgroupsize = StaticSize{groupsize} # we might have padded workgroupsize | ||||||
|
||||||
index_map = Oceananigans.Architectures.convert_args(arch, index_map) | ||||||
iterspace = NDRange{length(range), static_blocks, static_workgroupsize}(blocks, IndexMap(index_map)) | ||||||
|
||||||
return iterspace, dynamic | ||||||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.