Skip to content
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

Performance regression tests #388

Merged
merged 34 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
aadaa39
Add initial benchmarks for common assembly loops.
termi-official Oct 11, 2021
207f5f3
Some renaming, docs and introduction of face integrals.
termi-official Oct 11, 2021
84a6a15
Introduce grid benchmarks.
termi-official Oct 11, 2021
6516fb7
Further improvement on naming and introduce benchmark on dof numberin…
termi-official Oct 12, 2021
dcd73bc
Some notes, code clean up and Dirichlet benchmarks.
termi-official Oct 12, 2021
b244fbc
Apply suggestions from Maxi's code review
termi-official Oct 12, 2021
2bd59c4
Fix small derp.
termi-official Oct 12, 2021
dbca657
Add Serendipity assembly benchmarks.
termi-official Oct 12, 2021
eab8180
Fix another derp.
termi-official Oct 12, 2021
43347dd
Simplify Dirichlet benchmarks.
termi-official Oct 12, 2021
c95c541
Reduce benchmark workload.
termi-official Oct 13, 2021
71b63b1
Add Cell*Value constructors, because they are responsible for the hea…
termi-official Oct 20, 2021
80ce23e
Wrap benchmarks into subproject.
termi-official Oct 19, 2022
27f759e
Hotfix Manifest.toml
termi-official Oct 19, 2022
6e666fb
Remove manifest for now.
Feb 28, 2023
7bed3bb
Change gitignore for testing.
Feb 28, 2023
203d4de
Add PkgBenchmark to Ferrite
Feb 28, 2023
dadc17f
Cleanup packages.
Feb 28, 2023
f3ea21d
Add makefile for benchmark and regression.
Feb 28, 2023
e226997
Enforce via makefile that the correct Ferrite.jl folder is used.
Feb 28, 2023
a6a7bec
Add docs about benchmarking
Feb 28, 2023
849f360
Split up into several files.
Feb 28, 2023
fbcdb3a
Allow some control on which benchmarks will run.
Feb 28, 2023
4020db9
Fix benchmarking namespace issue.
Feb 28, 2023
890c1a7
Add information about running benchmark subsets.
Feb 28, 2023
ac73589
Clean gitignore.
Feb 28, 2023
fc0fd4f
Move benchmark docs into development docs.
Mar 2, 2023
f71a052
refiix mixed
fredrikekre Mar 15, 2023
42637cb
fix
fredrikekre Mar 15, 2023
d5eba95
foobar
fredrikekre Mar 15, 2023
8a390fb
foooo
fredrikekre Mar 15, 2023
9925cc2
fdsfsd
fredrikekre Mar 15, 2023
3910706
fds
fredrikekre Mar 15, 2023
f7d9bdf
fdsf
fredrikekre Mar 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
*.jl.*.cov
*.jl.mem
*.vtu
*.vtk
*.pvtu
*.pvtk
*.pvd
examples/.ipynb_checkpoints/
docs/build/
Expand All @@ -10,3 +13,8 @@ docs/src/examples/
*.DS_Store
/Manifest.toml
/test/coverage/Manifest.toml
/benchmark/Manifest.toml

LocalPreferences.toml
docs/LocalPreferences.toml
benchmark/tune.json
18 changes: 9 additions & 9 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Tensors = "48a634ad-e948-5137-8d70-aa71f2a747f4"
WriteVTK = "64499a7a-5c06-52f2-abe2-ccb03c286192"

[weakdeps]
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
Metis = "2679e427-3c69-5b7f-982b-ece356f1e94b"

[extensions]
FerriteBlockArrays = "BlockArrays"
FerriteMetis = "Metis"

[compat]
BlockArrays = "0.16"
EnumX = "1"
Expand All @@ -31,13 +23,18 @@ Tensors = "1"
WriteVTK = "1.13"
julia = "1.6"

[extensions]
FerriteBlockArrays = "BlockArrays"
FerriteMetis = "Metis"

[extras]
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
FerriteGmsh = "4f95f4f8-b27c-4ae5-9a39-ea55e634e36b"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
Gmsh = "705231aa-382f-11e9-3f0c-b7cb4346fdeb"
IterativeSolvers = "42fd0dbc-a981-5370-80f2-aaf504508153"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
Metis = "2679e427-3c69-5b7f-982b-ece356f1e94b"
NBInclude = "0db19996-df87-5ea3-a455-e3a50d440464"
ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca"
Expand All @@ -46,7 +43,10 @@ SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"

[targets]
test = ["BlockArrays", "Downloads", "FerriteGmsh", "ForwardDiff", "Gmsh", "IterativeSolvers", "Metis", "NBInclude", "ProgressMeter", "Random", "SHA", "StableRNGs", "Test", "TimerOutputs", "Logging"]

[weakdeps]
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
Metis = "2679e427-3c69-5b7f-982b-ece356f1e94b"
26 changes: 26 additions & 0 deletions benchmark/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Allow custom julia commands
JULIA_CMD ?= julia

BENCHMARK_DIR := $(shell dirname $(abspath $(firstword $(MAKEFILE_LIST))))

default: benchmark

clean:
rm Manifest.toml

Manifest.toml:
${JULIA_CMD} --project=${BENCHMARK_DIR} -e 'using Pkg; Pkg.develop(path=".."); Pkg.instantiate(); Pkg.precompile();'

benchmark: Manifest.toml
${JULIA_CMD} --project=${BENCHMARK_DIR} ${BENCHMARK_DIR}/runbenchmarks.jl benchmark/benchmarks.jl

benchmark-%: Manifest.toml
${JULIA_CMD} --project=${BENCHMARK_DIR} ${BENCHMARK_DIR}/runbenchmarks.jl benchmark/benchmarks.jl ${@:benchmark-%=%}

compare: Manifest.toml
${JULIA_CMD} --project=${BENCHMARK_DIR} ${BENCHMARK_DIR}/runcomparison.jl ${target} ${baseline} benchmark/benchmarks.jl

compare-%: Manifest.toml
${JULIA_CMD} --project=${BENCHMARK_DIR} ${BENCHMARK_DIR}/runcomparison.jl ${target} ${baseline} benchmark/benchmarks.jl ${@:benchmark-%=%}

.PHONY: default clean benchmark benchmark-% compare compare-%
4 changes: 4 additions & 0 deletions benchmark/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
Ferrite = "c061ca5d-56c9-439f-9c0e-210fe06d3992"
PkgBenchmark = "32113eaa-f34f-5b0d-bd6c-c81e245fc73d"
70 changes: 70 additions & 0 deletions benchmark/benchmarks-assembly.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#----------------------------------------------------------------------#
# Assembly functionality benchmarks
#----------------------------------------------------------------------#
SUITE["assembly"] = BenchmarkGroup()

# Permute over common combinations for some commonly required local matrices.
SUITE["assembly"]["common-local"] = BenchmarkGroup()
COMMON_LOCAL_ASSEMBLY = SUITE["assembly"]["common-local"]
for spatial_dim ∈ 1:3
ξ_dummy = Vec{spatial_dim}(ntuple(x->0.0, spatial_dim))
COMMON_LOCAL_ASSEMBLY["spatial-dim",spatial_dim] = BenchmarkGroup()
for geo_type ∈ FerriteBenchmarkHelper.geo_types_for_spatial_dim(spatial_dim)
COMMON_LOCAL_ASSEMBLY["spatial-dim",spatial_dim][string(geo_type)] = BenchmarkGroup()

grid = generate_grid(geo_type, tuple(repeat([1], spatial_dim)...));
ref_type = FerriteBenchmarkHelper.default_refshape(geo_type)
ip_geo = Ferrite.default_interpolation(geo_type)

# Nodal interpolation tests
for order ∈ 1:2, ip_type ∈ [Lagrange, Serendipity]
ip = ip_type{spatial_dim, ref_type, order}()

# Skip over elements which are not implemented
!applicable(Ferrite.value, ip, 1, ξ_dummy) && continue

qr = QuadratureRule{spatial_dim, ref_type}(2*order-1)

# Currenlty we just benchmark nodal Lagrange bases.
COMMON_LOCAL_ASSEMBLY["spatial-dim",spatial_dim][string(geo_type)][string(ip_type),string(order)] = BenchmarkGroup()
LAGRANGE_SUITE = COMMON_LOCAL_ASSEMBLY["spatial-dim",spatial_dim][string(geo_type)][string(ip_type),string(order)]
LAGRANGE_SUITE["fe-values"] = BenchmarkGroup()
LAGRANGE_SUITE["ritz-galerkin"] = BenchmarkGroup()
LAGRANGE_SUITE["petrov-galerkin"] = BenchmarkGroup()

# Note: at the time of writing this PR the ctor makes the heavy lifting and caches important values.
LAGRANGE_SUITE["fe-values"]["scalar"] = @benchmarkable CellScalarValues($qr, $ip, $ip_geo);
LAGRANGE_SUITE["fe-values"]["vector"] = @benchmarkable CellVectorValues($qr, $ip, $ip_geo);

csv = CellScalarValues(qr, ip, ip_geo);
csv2 = CellScalarValues(qr, ip, ip_geo);

cvv = CellVectorValues(qr, ip, ip_geo);
cvv2 = CellVectorValues(qr, ip, ip_geo);

# Scalar shape φ and test ψ: ∫ φ ψ
LAGRANGE_SUITE["ritz-galerkin"]["mass"] = @benchmarkable FerriteAssemblyHelper._generalized_ritz_galerkin_assemble_local_matrix($grid, $csv, shape_value, shape_value, *)
LAGRANGE_SUITE["petrov-galerkin"]["mass"] = @benchmarkable FerriteAssemblyHelper._generalized_petrov_galerkin_assemble_local_matrix($grid, $csv, shape_value, $csv2, shape_value, *)
# Vectorial shape φ and test ψ: ∫ φ ⋅ ψ
LAGRANGE_SUITE["ritz-galerkin"]["vector-mass"] = @benchmarkable FerriteAssemblyHelper._generalized_ritz_galerkin_assemble_local_matrix($grid, $cvv, shape_value, shape_value, ⋅)
LAGRANGE_SUITE["petrov-galerkin"]["vector-mass"] = @benchmarkable FerriteAssemblyHelper._generalized_petrov_galerkin_assemble_local_matrix($grid, $cvv, shape_value, $cvv2, shape_value, ⋅)
# Scalar shape φ and test ψ: ∫ ∇φ ⋅ ∇ψ
LAGRANGE_SUITE["ritz-galerkin"]["Laplace"] = @benchmarkable FerriteAssemblyHelper._generalized_ritz_galerkin_assemble_local_matrix($grid, $csv, shape_gradient, shape_gradient, ⋅)
LAGRANGE_SUITE["petrov-galerkin"]["Laplace"] = @benchmarkable FerriteAssemblyHelper._generalized_petrov_galerkin_assemble_local_matrix($grid, $csv, shape_gradient, $csv2, shape_gradient, ⋅)
# Vectorial shape φ and test ψ: ∫ ∇φ : ∇ψ
LAGRANGE_SUITE["ritz-galerkin"]["vector-Laplace"] = @benchmarkable FerriteAssemblyHelper._generalized_ritz_galerkin_assemble_local_matrix($grid, $cvv, shape_gradient, shape_gradient, ⊡)
LAGRANGE_SUITE["petrov-galerkin"]["vector-Laplace"] = @benchmarkable FerriteAssemblyHelper._generalized_petrov_galerkin_assemble_local_matrix($grid, $cvv, shape_gradient, $cvv2, shape_gradient, ⊡)
# Vectorial shape φ and scalar test ψ: ∫ (∇ ⋅ φ) ψ
LAGRANGE_SUITE["petrov-galerkin"]["pressure-velocity"] = @benchmarkable FerriteAssemblyHelper._generalized_petrov_galerkin_assemble_local_matrix($grid, $cvv, shape_divergence, $csv, shape_value, *)

if spatial_dim > 1
qr_face = QuadratureRule{spatial_dim-1, ref_type}(2*order-1)
fsv = FaceScalarValues(qr_face, ip, ip_geo);
fsv2 = FaceScalarValues(qr_face, ip, ip_geo);

LAGRANGE_SUITE["ritz-galerkin"]["face-flux"] = @benchmarkable FerriteAssemblyHelper._generalized_ritz_galerkin_assemble_local_matrix($grid, $fsv, shape_gradient, shape_value, *)
LAGRANGE_SUITE["petrov-galerkin"]["face-flux"] = @benchmarkable FerriteAssemblyHelper._generalized_petrov_galerkin_assemble_local_matrix($grid, $fsv, shape_gradient, $fsv2, shape_value, *)
end
end
end
end
44 changes: 44 additions & 0 deletions benchmark/benchmarks-boundary-conditions.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#----------------------------------------------------------------------#
# Boundary condition benchmarks
#----------------------------------------------------------------------#
SUITE["boundary-conditions"] = BenchmarkGroup()

SUITE["boundary-conditions"]["Dirichlet"] = BenchmarkGroup()
DIRICHLET_SUITE = SUITE["boundary-conditions"]["Dirichlet"]
# span artifical scope...
for spatial_dim ∈ [2]
# Benchmark application on global system
DIRICHLET_SUITE["global"] = BenchmarkGroup()

geo_type = Quadrilateral
grid = generate_grid(geo_type, ntuple(x->2, spatial_dim));
ref_type = FerriteBenchmarkHelper.default_refshape(geo_type)
ip_geo = Ferrite.default_interpolation(geo_type)
order = 2

# assemble a mass matrix to apply BCs on (because its cheap)
ip = Lagrange{spatial_dim, ref_type, order}()
qr = QuadratureRule{spatial_dim, ref_type}(2*order-1)
cellvalues = CellScalarValues(qr, ip, ip_geo);
dh = DofHandler(grid)
push!(dh, :u, 1, ip)
close!(dh);

ch = ConstraintHandler(dh);
∂Ω = union(getfaceset.((grid, ), ["left"])...);
dbc = Dirichlet(:u, ∂Ω, (x, t) -> 0)
add!(ch, dbc);
close!(ch);

# Non-symmetric application
M, f = FerriteAssemblyHelper._assemble_mass(dh, cellvalues, false);
DIRICHLET_SUITE["global"]["apply!(M,f,APPLY_TRANSPOSE)"] = @benchmarkable apply!($M, $f, $ch; strategy=$(Ferrite.APPLY_TRANSPOSE));
DIRICHLET_SUITE["global"]["apply!(M,f,APPLY_INPLACE)"] = @benchmarkable apply!($M, $f, $ch; strategy=$(Ferrite.APPLY_INPLACE));
# Symmetric application
M, f = FerriteAssemblyHelper._assemble_mass(dh, cellvalues, true);
DIRICHLET_SUITE["global"]["apply!(M_sym,f,APPLY_TRANSPOSE)"] = @benchmarkable apply!($M, $f, $ch; strategy=$(Ferrite.APPLY_TRANSPOSE));
DIRICHLET_SUITE["global"]["apply!(M_sym,f,APPLY_INPLACE)"] = @benchmarkable apply!($M, $f, $ch; strategy=$(Ferrite.APPLY_INPLACE));

DIRICHLET_SUITE["global"]["apply!(f)"] = @benchmarkable apply!($f, $ch);
DIRICHLET_SUITE["global"]["apply_zero!(f)"] = @benchmarkable apply!($f, $ch);
end
92 changes: 92 additions & 0 deletions benchmark/benchmarks-dofs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@

#----------------------------------------------------------------------#
# Benchmarks around the dof management
#----------------------------------------------------------------------#
SUITE["dof-management"] = BenchmarkGroup()
SUITE["dof-management"]["numbering"] = BenchmarkGroup()
# !!! NOTE close! must wrapped into a custom function, because consecutive calls to close!, since the dofs are already distributed.
NUMBERING_SUITE = SUITE["dof-management"]["numbering"]
for spatial_dim ∈ [3]# 1:3
NUMBERING_SUITE["spatial-dim",spatial_dim] = BenchmarkGroup()
for geo_type ∈ FerriteBenchmarkHelper.geo_types_for_spatial_dim(spatial_dim)
NUMBERING_SUITE["spatial-dim",spatial_dim][string(geo_type)] = BenchmarkGroup()

ref_type = FerriteBenchmarkHelper.default_refshape(geo_type)

for grid_size ∈ [2]#[3, 6, 9] #multiple grid sized to estimate computational complexity...
NUMBERING_SUITE["spatial-dim",spatial_dim][string(geo_type)]["grid-size-",grid_size] = BenchmarkGroup()
NUMBERING_SUITE["spatial-dim",spatial_dim][string(geo_type)]["grid-size-",grid_size] = BenchmarkGroup()

grid = generate_grid(geo_type, ntuple(x->grid_size, spatial_dim));

for field_dim ∈ [3]#1:3
NUMBERING_SUITE["spatial-dim",spatial_dim][string(geo_type)]["grid-size-",grid_size]["field-dim-", field_dim] = BenchmarkGroup()
NUMBERING_FIELD_DIM_SUITE = NUMBERING_SUITE["spatial-dim",spatial_dim][string(geo_type)]["grid-size-",grid_size]["field-dim-", field_dim]
# Lagrange tests
for order ∈ 1:2
ip = Lagrange{spatial_dim, ref_type, order}()

# Skip over elements which are not implemented
ξ_dummy = Vec{spatial_dim}(ntuple(x->0.0, spatial_dim))
!applicable(Ferrite.value, ip, 1, ξ_dummy) && continue
!applicable(Ferrite.value, ip, 1, ξ_dummy) && continue

NUMBERING_FIELD_DIM_SUITE["Lagrange",order] = BenchmarkGroup()
LAGRANGE_SUITE = NUMBERING_FIELD_DIM_SUITE["Lagrange",order]
order2 = max(order-1, 1)
ip2 = Lagrange{spatial_dim, ref_type, order2}()

LAGRANGE_SUITE["DofHandler"] = BenchmarkGroup()

close_helper = function(grid, ip)
dh = DofHandler(grid)
push!(dh, :u, field_dim, ip)
close!(dh)
end
LAGRANGE_SUITE["DofHandler"]["one-field"] = @benchmarkable $close_helper($grid, $ip)

close_helper = function(grid, ip, ip2)
dh = DofHandler(grid)
push!(dh, :u, field_dim, ip)
push!(dh, :p, 1, ip2)
close!(dh)
end
LAGRANGE_SUITE["DofHandler"]["two-fields"] = @benchmarkable $close_helper($grid, $ip, $ip2)


LAGRANGE_SUITE["MixedDofHandler"] = BenchmarkGroup()
f1 = Field(:u, ip, field_dim)
f2 = Field(:p, ip2, 1)

close_helper = function(grid, f1)
dh = MixedDofHandler(grid)
push!(dh, FieldHandler([f1], Set(1:getncells(grid))))
close!(dh)
end
LAGRANGE_SUITE["MixedDofHandler"]["one-field"] = @benchmarkable $close_helper($grid, $f1)

close_helper = function(grid, f1)
dh = MixedDofHandler(grid)
push!(dh, FieldHandler([f1], Set(1:Int(round(getncells(grid)/2)))))
close!(dh)
end
LAGRANGE_SUITE["MixedDofHandler"]["one-field-subdomain"] = @benchmarkable $close_helper($grid, $f1)

close_helper = function(grid, f1, f2)
dh = MixedDofHandler(grid)
push!(dh, FieldHandler([f1, f2], Set(1:getncells(grid))))
close!(dh)
end
LAGRANGE_SUITE["MixedDofHandler"]["two-fields"] = @benchmarkable $close_helper($grid, $f1, $f2)

close_helper = function(grid, f1, f2)
dh = MixedDofHandler(grid)
push!(dh, FieldHandler([f1, f2], Set(1:Int(round(getncells(grid)/2)))))
close!(dh)
end
LAGRANGE_SUITE["MixedDofHandler"]["two-fields-subdomain"] = @benchmarkable $close_helper($grid, $f1, $f2)
end
end
end
end
end
21 changes: 21 additions & 0 deletions benchmark/benchmarks-mesh.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

#----------------------------------------------------------------------#
# Benchmarks for mesh functionality within Ferrite
#----------------------------------------------------------------------#
SUITE["mesh"] = BenchmarkGroup()

# Generator benchmarks
SUITE["mesh"]["generator"] = BenchmarkGroup()

# Strucutred hyperrectangle generators
SUITE["mesh"]["generator"]["hyperrectangle"] = BenchmarkGroup()
HYPERRECTANGLE_GENERATOR = SUITE["mesh"]["generator"]["hyperrectangle"]
for spatial_dim ∈ 1:3
HYPERRECTANGLE_GENERATOR["spatial-dim",spatial_dim] = BenchmarkGroup()
for geo_type ∈ FerriteBenchmarkHelper.geo_types_for_spatial_dim(spatial_dim)
HYPERRECTANGLE_GENERATOR["spatial-dim",spatial_dim][string(geo_type)] = @benchmarkable generate_grid($geo_type, $(ntuple(x->4, spatial_dim)));
end
end

# TODO AMR performance
# TODO topology performance
22 changes: 22 additions & 0 deletions benchmark/benchmarks.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using BenchmarkTools
using Ferrite

const selected = get(ENV, "FERRITE_SELECTED_BENCHMARKS", "all")
const runall = selected == "all"

include("helper.jl")

const SUITE = BenchmarkGroup()

if runall || selected == "mesh"
include("benchmarks-mesh.jl")
end
if runall || selected == "dofs"
include("benchmarks-dofs.jl")
end
if runall || selected == "assembly"
include("benchmarks-assembly.jl")
end
if runall || selected == "boundary-conditions"
include("benchmarks-boundary-conditions.jl")
end
Loading