Skip to content

Commit

Permalink
Merge pull request #1039 from gridap/benchmarks
Browse files Browse the repository at this point in the history
Benchmarks
  • Loading branch information
JordiManyer authored Nov 5, 2024
2 parents e4645af + c657b3a commit ba8681c
Show file tree
Hide file tree
Showing 13 changed files with 273 additions and 15 deletions.
56 changes: 56 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Benchmarks

on:
workflow_dispatch:
inputs:
target:
description: 'Target branch'
required: true
type: string
base:
description: 'Base branch'
required: true
default: 'master'
type: string

jobs:
benchmark:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
version:
- '1.10'
arch:
- x64
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: actions/cache@v4
env:
cache-name: cache-artifacts
with:
path: ~/.julia/artifacts
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
restore-keys: |
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- uses: julia-actions/julia-buildpkg@v1
- name: Install Gridap in main environment
run: julia -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Install dependencies
run: julia --project=benchmark/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Run benchmarks
run: julia --project=benchmark/ --color=yes benchmark/run_benchmarks.jl
env:
BM_BASE: ${{ github.event.inputs.base }}
BM_TARGET: ${{ github.event.inputs.target }}
- uses: actions/upload-artifact@v4
with:
name: benchmarks
path: benchmark/benchmark_results.md
18 changes: 10 additions & 8 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added Barycentric refinement rule in 2D and 3D. Added Simplexify refinement rule. Since PR[#1024](https://github.com/gridap/Gridap.jl/pull/1024).
- Added names to vector and tensor components in VTK exports, to avoid Paraview's automatic (sometimes wrong) guesses. See `TensorValues.indep_components_names`. Since PR[#1038](https://github.com/gridap/Gridap.jl/pull/1038).
- Misc improvements of the `TensorValues` module: See `TensorValues.indep_components_names`. Since PR[#1040](https://github.com/gridap/Gridap.jl/pull/1040).
- Documented all symbols exported by the module
- Improved and added test for some API function of `MultiValue` (general `diag` of 2nd order tensors, fixed `convert` of 3rd order tensors to SArray, avoid unwanted fallback of `num_components` on `MultiValue` types with undefined dimensions, more autodiff tests, better `double_contraction` API (prevent invalid operation giving indexing errors and enable valid operations)).
- Added a clear separation between the physical components access (`getindex`, `num_components`) and the numerical access to the stored independent components (`num_indep_components`, `indep_comp_getindex`) to enable using symmetric tensor types as unknown in FE Spaces.
- Implemented automatic differentiation `gradient` and `laplacian` for second order tensor, and `divergence` for third order tensors.
- Added `AbstractSymTensorValue`, an abstract type for second order symmetric tensors, and `SymTracelessTensorValue` (aliased to `QTensorValue`), a type for traceless symmetric tensors. `SymTensorValue` is now subtype of `AbstractSymTensorValue`.
- A convergence test for Poisson problem of `QTensorValue` unknown field validates the implementation.
- Documented all symbols exported by the module
- Improved and added test for some API function of `MultiValue` (general `diag` of 2nd order tensors, fixed `convert` of 3rd order tensors to SArray, avoid unwanted fallback of `num_components` on `MultiValue` types with undefined dimensions, more autodiff tests, better `double_contraction` API (prevent invalid operation giving indexing errors and enable valid operations)).
- Added a clear separation between the physical components access (`getindex`, `num_components`) and the numerical access to the stored independent components (`num_indep_components`, `indep_comp_getindex`) to enable using symmetric tensor types as unknown in FE Spaces.
- Implemented automatic differentiation `gradient` and `laplacian` for second order tensor, and `divergence` for third order tensors.
- Added `AbstractSymTensorValue`, an abstract type for second order symmetric tensors, and `SymTracelessTensorValue` (aliased to `QTensorValue`), a type for traceless symmetric tensors. `SymTensorValue` is now subtype of `AbstractSymTensorValue`.
- A convergence test for Poisson problem of `QTensorValue` unknown field validates the implementation.
- Added support for benchmarking, through `PkgBenchmark.jl`. Since PR[#1039](https://github.com/gridap/Gridap.jl/pull/1039).
- Added code quality tests, through `Aqua.jl`. Since PR[#1039](https://github.com/gridap/Gridap.jl/pull/1039).

### Fixed
### Fixed

- Fixed constructor of RungeKutta with only one solver. Since PR[#999](https://github.com/gridap/Gridap.jl/pull/999).
- Fixed constructor of RungeKutta with only one solver. Since PR[#999](https://github.com/gridap/Gridap.jl/pull/999).

## [0.18.6] - 2024-08-29

Expand Down
9 changes: 8 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ WriteVTK = "64499a7a-5c06-52f2-abe2-ccb03c286192"

[compat]
AbstractTrees = "0.3.3, 0.4"
Aqua = "0.8"
BSON = "0.2.5, 0.3"
BlockArrays = "0.12.12, 0.13, 0.14, 0.15, 0.16"
Combinatorics = "1.0.0"
Expand All @@ -45,18 +46,24 @@ ForwardDiff = "0.10.10"
JLD2 = "0.1.11, 0.3, 0.4, 0.5"
JSON = "0.21.0"
LineSearches = "7.0.1"
LinearAlgebra = "1"
NLsolve = "4.3.0"
NearestNeighbors = "0.4.8"
PolynomialBases = "0.4.12"
Preferences = "1.4"
QuadGK = "2.3.1, 2.4"
Random = "1"
SparseArrays = "1"
SparseMatricesCSR = "0.6.4"
StaticArrays = "0.12.1, 1.0"
Statistics = "1"
Test = "1"
WriteVTK = "1.12.0"
julia = "1.3"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
test = ["Aqua", "Test"]
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"
Gridap = "56d4f2e9-7ea1-5844-9cf6-b9c51ca7ce8e"
PkgBenchmark = "32113eaa-f34f-5b0d-bd6c-c81e245fc73d"
59 changes: 59 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Benchmarking Suite

The following benchmarking suite uses `PkgBenchmark.jl` and `BenchmarkTools.jl` to compare the performance of different branches of Gridap.

## Running the benchmarks

### Running as CI job

The benchmarks are setup as a manual Github Actions workflow in `.github/workflows/benchmark.yml`. To run the workflow, you will need administrator access to the Gridap repository, then follow instructions [here](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/manually-running-a-workflow).

The workflow will has two inputs: `target` and `base`, which are the branches/tags/commits you want to compare. The workflow will run the benchmarks on the `target` branch and compare them with the `base` branch (`master` by default).

You can also run the workflow using Github CLI and the following command:

```bash
gh workflow run benchmark.yml -f target=your_target_branch -f base=your_base_branch
```

### Running Locally

To run the benchmarks locally, you can have a look at the [documentation for `PkgBenchmark.jl`](https://juliaci.github.io/PkgBenchmark.jl/stable/run_benchmarks/).

Alternatively, you can run the CI script locally from a local copy of the repository. From the Gridap root directory, run the following commands:

```bash
# Instantiate Gridap and Gridap/benchmark
julia -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
julia --project=benchmark/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
# Run the benchmarks
export BM_TARGET = "your target branch"
export BM_BASE = "your reference branch"
julia --project=benchmark/ --color=yes benchmark/run_benchmarks.jl
```

where `BM_TARGET` and `BM_BASE` are the branches/tags/commits you want to compare.

## Adding a new benchmark

To add a new benchmark suite `xyx`, create a new file `bm/bm_xyx.jl` that with the following structure:

```julia
module bm_xyx

using PkgBenchmark, BenchmarkTools

const SUITE = BenchmarkGroup()

[... Add your benchmarks here ...]

end # module
```

Then, add the following line to the `benchmarks.jl` file:

```julia
@include_bm "bm_xyz"
```

This should automatically include the new benchmarks into the global benchmarking suite.
14 changes: 14 additions & 0 deletions benchmark/benchmarks.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using BenchmarkTools
using PkgBenchmark
using Gridap

macro include_bm(SUITE,name)
quote
include("bm/$($name).jl")
SUITE["$($name)"] = $(Symbol(name)).SUITE
end
end

const SUITE = BenchmarkGroup()

@include_bm SUITE "bm_assembly"
59 changes: 59 additions & 0 deletions benchmark/bm/bm_assembly.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module bm_assembly

using PkgBenchmark, BenchmarkTools
using Gridap
using Gridap.Geometry

mass(u,v,dΩ) = (uv)dΩ
laplacian(u,v,dΩ) = ((u)(v))dΩ
graddiv(u,v,dΩ) = ((∇u)(∇v))dΩ

function driver(
Ω :: Triangulation,
reffe :: Tuple,
qdegree :: Integer,
biform :: Function
)
model = get_background_model(Ω)
= Measure(Ω,qdegree)
V = TestFESpace(model, reffe)
a(u,v) = biform(u,v,dΩ)
A = assemble_matrix(a, V, V)
end

const SUITE = BenchmarkGroup()

for (D,n) in [(2,10),(3,6)]
domain = Tuple([repeat([0,1], D)...])
partition = Tuple(fill(n, D))
model = UnstructuredDiscreteModel(CartesianDiscreteModel(domain, partition))
trian_cases = [
("bulk",Triangulation(model)),
("view",Triangulation(model,collect(1:div(n^D,2)))), # About half of the cells
]
for (trian_name, trian) in trian_cases
for order in [1,2,3]
basis_cases = [
("lagrangian",lagrangian,Float64,order),
("vector_lagragian",lagrangian,VectorValue{D,Float64},order),
("raviart_thomas",raviart_thomas,Float64,order-1),
]
for (basis_name,basis,T,degree) in basis_cases
biform_cases = [
("mass",mass,2*order),
("laplacian",laplacian,2*(order-1)),
("graddiv",graddiv,2*(order-1)),
]
for (biform_name,biform,qdegree) in biform_cases
reffe = ReferenceFE(basis, T, degree)
name = "assembly_$(D)D_$(trian_name)_$(basis_name)_$(biform_name)_$(order)"
SUITE[name] = @benchmarkable driver(
$(trian),$(reffe),$(qdegree),$(biform)
)
end
end
end
end
end

end # module
28 changes: 28 additions & 0 deletions benchmark/run_benchmarks.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Pkg

Pkg.activate(@__DIR__)
Pkg.develop(PackageSpec(path = dirname(@__DIR__)))
Pkg.instantiate()

using Gridap
using PkgBenchmark

config_kwargs = (;
juliacmd = `julia -O3`,
)

if haskey(ENV,"BM_TARGET") # Provided by CI workflow
target = BenchmarkConfig(;config_kwargs..., id = ENV["BM_TARGET"])
else # Default to the current commit
target = BenchmarkConfig(;config_kwargs...)
end

if haskey(ENV,"BM_BASE") # Provided by CI workflow
base = BenchmarkConfig(;config_kwargs..., id = ENV["BM_BASE"])
else # Default to master
base = BenchmarkConfig(;config_kwargs..., id = "master")
end

results = judge(Gridap, target, base)
outfile = normpath(@__DIR__,"benchmark_results.md")
export_markdown(outfile,results)
2 changes: 0 additions & 2 deletions src/Geometry/Geometry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ export is_oriented
export is_regular
export expand_cell_data
export compress_cell_data
export compress_contributions
export compress_ids

export UnstructuredGridTopology

Expand Down
2 changes: 0 additions & 2 deletions src/ODEs/ODEs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ export StageOperator
export NonlinearStageOperator
export LinearStageOperator

export massless_residual_weights

include("ODESolvers.jl")

export ODESolver
Expand Down
2 changes: 0 additions & 2 deletions src/ReferenceFEs/ReferenceFEs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,10 @@ export get_face_moments
export get_face_nodes_dofs
export get_nodes
export evaluate!
export evaluate_dof
export return_cache
export return_type
export test_dof
export test_dof_array
# export evaluate_dof_array

export ReferenceFE
export ReferenceFEName
Expand Down
33 changes: 33 additions & 0 deletions test/Aqua.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module AquaTests

using Gridap
using Aqua

Aqua.test_all(
Gridap,
ambiguities = false,
unbound_args = false
)

"""
Comment: Ambiguities
I think all ambiguities are either false positives or never used in practice... I've seen
other packages set `ambiguities = false` as well, so I think it's fine to do so.
"""

"""
Comment: Unbound Args
We do have some unbound type warnings. However, these are calls which are never executed in
the code.
They mostly involve things like `f(a::T...) where T`, which trigger the warning
in the case were the function `f` is called with no arguments. This can be fixed as described
in https://juliatesting.github.io/Aqua.jl/stable/unbound_args/#test_unbound_args, but it is quite
a pain to do so...
I guess something to think about in the future.
"""

end
2 changes: 2 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ using Test

@time @testset "Adaptivity" begin include("AdaptivityTests/runtests.jl") end

@time @testset "Aqua" begin include("Aqua.jl") end

end # module

0 comments on commit ba8681c

Please sign in to comment.