Skip to content

Commit 31c1013

Browse files
committed
Unify DataLayouts and simplify API
1 parent c9757de commit 31c1013

149 files changed

Lines changed: 2929 additions & 9505 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.buildkite/pipeline.yml

Lines changed: 18 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -104,76 +104,31 @@ steps:
104104
- group: "Unit: DataLayouts"
105105
steps:
106106

107-
- label: "Unit: data0d"
108-
key: unit_data0d
107+
- label: "Unit: data fill and copyto (1 thread)"
108+
key: unit_data_fill_and_copyto
109109
retry: *retry_policy
110-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/data0d.jl"
110+
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_fill_and_copyto.jl"
111111

112-
- label: "Unit: data_fill"
113-
key: unit_data_fill
112+
- label: "Unit: data fill and copyto (4 threads)"
113+
key: threaded_unit_data_fill_and_copyto
114114
retry: *retry_policy
115-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_fill.jl"
115+
command: "julia --threads=4 --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_fill_and_copyto.jl"
116116

117-
- label: "Unit: data_copyto"
118-
key: unit_data_copyto
119-
retry: *retry_policy
120-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_copyto.jl"
121-
122-
- label: "Unit: cartesian_field_index"
123-
key: unit_data_cartesian_field_index
124-
retry: *retry_policy
125-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_cartesian_field_index.jl"
126-
127-
- label: "Unit: non_extruded_broadcast"
128-
key: unit_non_extruded_broadcast
129-
retry: *retry_policy
130-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_non_extruded_broadcast.jl"
131-
132-
- label: "Unit: mapreduce"
117+
- label: "Unit: mapreduce (1 thread)"
133118
key: unit_data_mapreduce
134119
retry: *retry_policy
135120
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_mapreduce.jl"
136121

122+
- label: "Unit: mapreduce (4 threads)"
123+
key: threaded_unit_data_mapreduce
124+
retry: *retry_policy
125+
command: "julia --threads=4 --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_mapreduce.jl"
126+
137127
- label: "Unit: data_opt_similar"
138128
key: data_opt_similar
139129
retry: *retry_policy
140130
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/opt_similar.jl"
141131

142-
- label: "Unit: opt_universal_size"
143-
key: opt_universal_size
144-
retry: *retry_policy
145-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/opt_universal_size.jl"
146-
147-
- label: "Unit: data_ndims"
148-
key: unit_data_ndims
149-
retry: *retry_policy
150-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_ndims.jl"
151-
152-
- label: "Unit: unit_data2array"
153-
key: unit_data2array
154-
retry: *retry_policy
155-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_data2array.jl"
156-
157-
- label: "Unit: data1d"
158-
key: unit_data1d
159-
retry: *retry_policy
160-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/data1d.jl"
161-
162-
- label: "Unit: data2d"
163-
key: unit_data2d
164-
retry: *retry_policy
165-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/data2d.jl"
166-
167-
- label: "Unit: data1dx"
168-
key: unit_data1dx
169-
retry: *retry_policy
170-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/data1dx.jl"
171-
172-
- label: "Unit: data2dx"
173-
key: unit_data2dx
174-
retry: *retry_policy
175-
command: "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/data2dx.jl"
176-
177132
- label: "Unit: data cuda"
178133
key: unit_data_cuda
179134
retry: *retry_policy
@@ -196,18 +151,18 @@ steps:
196151
agents:
197152
slurm_gpus: 1
198153

199-
- label: "Unit: data fill"
200-
key: gpu_unit_data_fill
154+
- label: "Unit: data fill and copyto (1 gpu)"
155+
key: gpu_unit_data_fill_and_copyto
201156
retry: *retry_policy
202157
command:
203158
- "julia --project=.buildkite -e 'using CUDA; CUDA.versioninfo()'"
204-
- "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_fill.jl"
159+
- "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_fill_and_copyto.jl"
205160
env:
206161
CLIMACOMMS_DEVICE: "CUDA"
207162
agents:
208163
slurm_gpus: 1
209164

210-
- label: "Unit: data mapreduce"
165+
- label: "Unit: data mapreduce (1 gpu)"
211166
key: gpu_unit_data_mapreduce
212167
retry: *retry_policy
213168
command:
@@ -233,17 +188,6 @@ steps:
233188
modules: mpiwrapper/2024_05_27 climacommon/2026_02_18
234189
soft_fail: true # remove this after library issues are fixed
235190

236-
- label: "Unit: data copyto"
237-
key: gpu_unit_data_copyto
238-
retry: *retry_policy
239-
command:
240-
- "julia --project=.buildkite -e 'using CUDA; CUDA.versioninfo()'"
241-
- "julia --color=yes --check-bounds=yes --project=.buildkite test/DataLayouts/unit_copyto.jl"
242-
env:
243-
CLIMACOMMS_DEVICE: "CUDA"
244-
agents:
245-
slurm_gpus: 1
246-
247191
- group: "Unit: Geometry"
248192
steps:
249193

@@ -1624,27 +1568,11 @@ steps:
16241568
- group: "Perf: DataLayouts"
16251569
steps:
16261570

1627-
- label: "Perf: DataLayouts fill"
1628-
key: "cpu_datalayouts_fill"
1629-
retry: *retry_policy
1630-
command: "julia --color=yes --project=.buildkite test/DataLayouts/benchmark_fill.jl"
1631-
16321571
- label: "Perf: DataLayouts copyto!"
16331572
key: "cpu_datalayouts_copyto"
16341573
retry: *retry_policy
16351574
command: "julia --color=yes --project=.buildkite test/DataLayouts/benchmark_copyto.jl"
16361575

1637-
- label: "Perf: DataLayouts fill"
1638-
key: "gpu_datalayouts_fill"
1639-
retry: *retry_policy
1640-
command:
1641-
- "julia --project=.buildkite -e 'using CUDA; CUDA.versioninfo()'"
1642-
- "julia --color=yes --project=.buildkite test/DataLayouts/benchmark_fill.jl"
1643-
env:
1644-
CLIMACOMMS_DEVICE: "CUDA"
1645-
agents:
1646-
slurm_gpus: 1
1647-
16481576
- label: "Perf: DataLayouts copyto"
16491577
key: "gpu_datalayouts_copyto"
16501578
retry: *retry_policy
@@ -2093,7 +2021,7 @@ steps:
20932021
env:
20942022
TEST_NAME: "sphere/baroclinic_wave_rhoe_hf"
20952023
FLOAT_TYPE: "Float32"
2096-
horizontal_layout_type: "IJHF"
2024+
horizontal_layout_type: "VIJHF"
20972025
CLIMACOMMS_DEVICE: "CUDA"
20982026
agents:
20992027
slurm_gpus: 1
@@ -2414,7 +2342,7 @@ steps:
24142342
env:
24152343
TEST_NAME: "sphere/baroclinic_wave_rhoe_hf"
24162344
FLOAT_TYPE: "Float64"
2417-
horizontal_layout_type: "IJHF"
2345+
horizontal_layout_type: "VIJHF"
24182346

24192347
- label: ":computer: 3D sphere baroclinic wave (ρe)"
24202348
key: "cpu_baroclinic_wave_rho_e"

benchmarks/scripts/index_swapping.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function custom_kernel_knl_bc_1swap!(y1, bc, us)
106106
if tidx get_N(us)
107107
n = (get_Nij(us), get_Nij(us), 1, get_Nv(us), get_Nh(us))
108108
GCI = CartesianIndices(map(x -> Base.OneTo(x), n))[tidx]
109-
# Perform index swap (as in `getindex(::AbstractData, ::CartesianIndex)`)
109+
# Perform index swap (as in `getindex(::DataLayout, ::CartesianIndex)`)
110110
i, j, _, v, h = GCI.I
111111
CI = CartesianIndex(v, i, j, 1, h)
112112
y1[CI] = bc[CI]
@@ -140,7 +140,7 @@ function custom_kernel_knl_bc_2swap!(y1, bc, us)
140140
(v, i, j, _, h) = CIK.I
141141
GCI = CartesianIndex(i, j, 1, v, h)
142142

143-
# Swap again (in `getindex(::AbstractData, ::CartesianIndex)`)
143+
# Swap again (in `getindex(::DataLayout, ::CartesianIndex)`)
144144
(i, j, _, v, h) = GCI.I
145145
CI = CartesianIndex(v, i, j, 1, h)
146146
y1[CI] = bc[CI]

benchmarks/scripts/thermo_bench.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ using Test
154154
)
155155
x = fill((; ts = nt_ts, nt_core...), cspace)
156156
xv = fill((; ts = nt_ts, nt_core...), cspace)
157-
(_, Nij, _, Nv, Nh) = size(Fields.field_values(x.ts))
157+
(Nv, Nij, _, Nh) = size(Fields.field_values(x.ts))
158158
us = TB.UniversalSizesStatic(Nv, Nij, Nh)
159159
function to_vec(ξ)
160160
pns = propertynames(ξ)

benchmarks/scripts/thermo_bench_bw.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ using Test
180180
)
181181
x = fill((; ts = zero(TBB.PhaseEquil{FT}), nt_core...), cspace)
182182
xv = fill((; ts = nt_ts, nt_core...), cspace)
183-
(_, Nij, _, Nv, Nh) = size(Fields.field_values(x.ts))
183+
(Nv, Nij, _, Nh) = size(Fields.field_values(x.ts))
184184
us = TBB.UniversalSizesStatic(Nv, Nij, Nh)
185185
function to_vec(ξ)
186186
pns = propertynames(ξ)

docs/clima_core_specific.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ ClimaCore.jl provides the dynamical core infrastructure for [CliMA](https://clim
4141
1. **`Field`** (`src/Fields/`) — the primary data type. A field wraps data on a space and supports broadcast, reductions, and operator application.
4242
2. **`Space`** (`src/Spaces/`) — represents a discretized function space (spectral element, finite-difference, or extruded hybrid). Constructed from a grid and a quadrature rule.
4343
3. **Operators** (`src/Operators/`) — lazy differential operators (gradient, divergence, curl, interpolation, restriction) that compose via Julia's broadcast system.
44-
4. **`DataLayout`** (`src/DataLayouts/`) — the storage backends (IJFH, VIJFH, VF, etc.) that determine memory layout for CPU vs GPU performance.
44+
4. **`DataLayout`** (`src/DataLayouts/`) — the storage backends (VIJFH, VIJHF, etc.) that determine memory layout for CPU vs GPU performance.
4545
5. **`MatrixFields`** (`src/MatrixFields/`) — banded-matrix field algebra used for implicit vertical solvers and Jacobian construction.
4646

4747
## Test groups

docs/src/APIs/datalayouts_api.md

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,10 @@ CurrentModule = ClimaCore
77
```@docs
88
DataLayouts
99
DataLayouts.DataF
10-
DataLayouts.IF
11-
DataLayouts.IJF
12-
DataLayouts.VF
13-
DataLayouts.IFH
14-
DataLayouts.IJFH
15-
DataLayouts.VIFH
1610
DataLayouts.VIJFH
17-
DataLayouts.IHF
18-
DataLayouts.IJHF
19-
DataLayouts.VIHF
2011
DataLayouts.VIJHF
12+
DataLayouts.VIH1
13+
DataLayouts.IH1JH2
2114
DataLayouts.bitcast_struct
2215
DataLayouts.default_basetype
2316
DataLayouts.check_basetype
@@ -26,6 +19,4 @@ DataLayouts.num_basetypes
2619
DataLayouts.struct_field_view
2720
DataLayouts.set_struct!
2821
DataLayouts.get_struct
29-
DataLayouts.parent_array_type
30-
DataLayouts.promote_parent_array_type
3122
```

docs/src/APIs/utilities_api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Utilities.unionall_type
99
Utilities.replace_type_parameter
1010
Utilities.fieldtype_vals
1111
Utilities.new
12+
Utilities.is_inferred_type
13+
Utilities.return_type
1214
Utilities.unsafe_eltype
1315
Utilities.safe_eltype
1416
```

docs/src/debugging.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,13 @@ only when the `condition` is true (in this case `has_nans || has_inf`).
140140
Now, when we run our example, we will see
141141
```julia
142142
julia> renormalized_energy(myrho, myP, myu)
143-
Infiltrating post_op_callback(::ClimaCore.DataLayouts.IJFH{Float64, 4, Array{Float64, 4}}, ::ClimaCore.DataLayouts.IJFH{Float64, 4, Array{Float64, 4}}, ::Vararg{Any}; kwargs::@Kwargs{})
143+
Infiltrating post_op_callback(::ClimaCore.DataLayouts.VIJFH{...}, ::ClimaCore.DataLayouts.VIJFH{...}, ::Vararg{Any}; kwargs::@Kwargs{})
144144
at REPL[40]:4
145145
infil>
146146
```
147147
Here, we are dropped into a new REPL with full access to the variables in the scope where the `NaN` occurred. However, because of how `post_op_callback`, this is at a low level within `ClimaCore`, which is typically not useful. Hence, the next step is to type `@trace`, which prints out
148148
```julia
149-
[1] post_op_callback(::ClimaCore.DataLayouts.IJFH{…}, ::ClimaCore.DataLayouts.IJFH{…}, ::Vararg{…}; kwargs::@Kwargs{})
149+
[1] post_op_callback(::ClimaCore.DataLayouts.VIJFH{…}, ::ClimaCore.DataLayouts.VIJFH{…}, ::Vararg{…}; kwargs::@Kwargs{})
150150
at REPL[40]:4
151151
[2] post_op_callback
152152
at REPL[40]:1
@@ -250,7 +250,7 @@ parts of the broadcasted object contains NaNs:
250250
```julia
251251
using StructuredPrinting
252252
import ClimaCore: DataLayouts
253-
highlight_nans(x::DataLayouts.AbstractData) = any(y->isnan(y), parent(x));
253+
highlight_nans(x::DataLayouts.DataLayout) = any(y->isnan(y), parent(x));
254254
highlight_nans(_) = false;
255255
bc = Infiltrator.safehouse.args[2]; # we know that argument 2 is the broadcasted object
256256
(; result) = Infiltrator.safehouse; # get the result

docs/src/masks.md

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -169,60 +169,6 @@ operations of mask-aware and mask-unaware:
169169
This was a design implementation detail, users should not generally depend on the results where `mask == 0`, in case this is changed in the future.
170170
- internal array operations (`fill!(parent(field), 0)`) mask-unaware.
171171

172-
## Temporary work-arounds
173-
174-
We can perform mask-aware reductions with the following work-around
175-
176-
```julia
177-
using ClimaComms
178-
ClimaComms.@import_required_backends
179-
import ClimaCore: Spaces, Fields, DataLayouts, Geometry, Operators
180-
using ClimaCore.CommonSpaces
181-
using Test
182-
183-
FT = Float64
184-
ᶜspace = ExtrudedCubedSphereSpace(FT;
185-
z_elem = 10,
186-
z_min = 0,
187-
z_max = 1,
188-
radius = 10,
189-
h_elem = 10,
190-
n_quad_points = 4,
191-
staggering = CellCenter(),
192-
enable_mask = true,
193-
)
194-
ᶠspace = Spaces.face_space(ᶜspace)
195-
ᶠcoords = Fields.coordinate_field(ᶠspace)
196-
197-
# Set the mask
198-
Spaces.set_mask!(ᶜspace) do coords
199-
coords.lat > 0.5
200-
end
201-
202-
# get the mask
203-
mask = Spaces.get_mask(ᶜspace)
204-
205-
# make a field of ones
206-
ᶜf = ones(ᶜspace) # ignores mask
207-
208-
# bitmask spanning datalayout
209-
bm = DataLayouts.full_bitmask(mask, Fields.field_values(ᶜf));
210-
211-
# mask-unaware integral (includes jacobian weighting)
212-
@show sum(ᶜf)
213-
214-
# mask-unaware sum (excludes jacobian weighting)
215-
@show sum(Fields.field_values(ᶜf))
216-
217-
# mask-aware sum (excludes jacobian)
218-
@show sum(parent(ᶜf)[bm])
219-
220-
# level mask
221-
ᶜf_lev = Fields.level(ᶜf, 1);
222-
bm_lev = DataLayouts.full_bitmask(mask, Fields.field_values(ᶜf_lev));
223-
@show sum(parent(ᶜf_lev)[bm_lev])
224-
```
225-
226172
## Developer docs
227173

228174
In order to support masks, we define their types in `DataLayouts`, since

examples/bickleyjet/bickleyjet_cg_invariant_hypervisc.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import ClimaCore:
99
Operators,
1010
Spaces,
1111
Topologies,
12-
Quadratures,
13-
DataLayouts
12+
Quadratures
1413
using OrdinaryDiffEqSSPRK: ODEProblem, solve, SSPRK33
1514

1615
using Logging
@@ -163,7 +162,7 @@ sol_global = []
163162
if usempi
164163
for sol_step in sol.u
165164
sol_step_values_global =
166-
DataLayouts.gather(context, Fields.field_values(sol_step))
165+
ClimaComms.gather(context, Fields.field_values(sol_step))
167166
if ClimaComms.iamroot(context)
168167
sol_step_global = Fields.Field(sol_step_values_global, global_space)
169168
push!(sol_global, sol_step_global)

0 commit comments

Comments
 (0)