Make empty field broadcasting a no-op
- Dominant language
- Julia
- Stars
- 117
- Forks
- 19
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 41
Description
**Is your feature request related to a problem? Please describe.**
Broadcasting over empty fields currently traverses the field and, unless there are sensible operations that we can perform with empty fields, it would be nice if these expressions short circuited to no-ops.
Here is a MWE showing that the cost is not nothing:
```julia
using Revise
import ClimaCore.Geometry as Geometry
import ClimaCore.Spaces as Spaces
import ClimaCore.Domains as Domains
import ClimaCore.Meshes as Meshes
import ClimaCore.Topologies as Topologies
import ClimaComms
import ClimaCore
function FieldFromNamedTuple(space, nt::NamedTuple)
cmv(z) = nt
return cmv.(Fields.coordinate_field(space))
end
function big_space(
::Type{FT};
helem = 16,
Nq = 5,
zelem = 100,
context = ClimaComms.SingletonCommsContext(),
) where {FT}
radius = FT(128)
zlim = (0, 1)
vertdomain = Domains.IntervalDomain(
Geometry.ZPoint{FT}(zlim[1]),
Geometry.ZPoint{FT}(zlim[2]);
boundary_tags = (:bottom, :top),
)
vertmesh = Meshes.IntervalMesh(vertdomain, nelems = zelem)
vtopology = Topologies.IntervalTopology(context, vertmesh)
vspace = Spaces.CenterFiniteDifferenceSpace(vtopology)
hdomain = Domains.SphereDomain(radius)
hmesh = Meshes.EquiangularCubedSphere(hdomain, helem)
htopology = Topologies.Topology2D(context, hmesh)
quad = Spaces.Quadratures.GLL{Nq}()
hspace = Spaces.SpectralElementSpace2D(htopology, quad)
return Spaces.ExtrudedFiniteDifferenceSpace(hspace, vspace)
end
space = big_space(Float64);
x = FieldFromNamedTuple(space, (;));
y = FieldFromNamedTuple(space, (;));
function do_nothing(x, y)
return nothing
end
function copy_to(x, y)
@. x = y
return nothing
end
using BenchmarkTools
@btime copy_to(x, y)
@btime do_nothing(x, y)
```
The cost is small, but I don't see why we can't skip these extra traversals. In addition, this also yields significantly less codegen:
```julia
julia> IntrospectionTools.@code_summary copy_to(x, y)
------------------------------------ Code summary
[ Info: `n_instructions` = 0
[ Info: `n_inbounds` = 124
[ Info: `n_jl_calls` = 0
[ Info: length(code_native): 8537
[ Info: length(code_llvm): 132005
[ Info: length(code_llvm)/length(code_native): 15.462691812111983
------------------------------------
julia> IntrospectionTools.@code_summary do_nothing(x, y)
------------------------------------ Code summary
[ Info: `n_instructions` = 0
[ Info: `n_inbounds` = 0
[ Info: `n_jl_calls` = 0
[ Info: length(code_native): 403
[ Info: length(code_llvm): 1134
[ Info: length(code_llvm)/length(code_native): 2.8138957816377173
------------------------------------
```
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by running the provided Julia MWE and comparing `copy_to(x, y)` with `do_nothing(x, y)`, especially the `@. x = y` operation on empty NamedTuples. Trace the broadcasting path used by `copy_to`; done means empty-field broadcasting becomes a no-op without traversing the field or generating the unnecessary code shown in the issue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- performance
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100