From 8ca272aad45e49d21ec547fbc1b47d33dbca50db Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Mon, 29 Jan 2024 15:47:45 +0100 Subject: [PATCH 1/9] draft MPI extension --- Project.toml | 12 ++++++++++++ ext/TrixiBaseMPIExt.jl | 21 +++++++++++++++++++++ src/trixi_include.jl | 9 +++++++++ test/dummy.jl | 1 + 4 files changed, 43 insertions(+) create mode 100644 ext/TrixiBaseMPIExt.jl create mode 100644 test/dummy.jl diff --git a/Project.toml b/Project.toml index 9b13411..dfbbb68 100644 --- a/Project.toml +++ b/Project.toml @@ -2,3 +2,15 @@ name = "TrixiBase" uuid = "9a0f1c46-06d5-4909-a5a3-ce25d3fa3284" authors = ["Michael Schlottke-Lakemper "] version = "0.1.0" + +[weakdeps] +MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" + +[extensions] +TrixiBaseMPIExt = "MPI" + +[compat] +julia = "1.8" + +[extras] +MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" diff --git a/ext/TrixiBaseMPIExt.jl b/ext/TrixiBaseMPIExt.jl new file mode 100644 index 0000000..a99443f --- /dev/null +++ b/ext/TrixiBaseMPIExt.jl @@ -0,0 +1,21 @@ +# Package extension for adding MPI-based features to TrixiBase.jl +module TrixiBaseMPIExt +__precompile__(false) + +# Load package extension code on Julia v1.9 and newer +if isdefined(Base, :get_extension) + using MPI: MPI +end +import TrixiBase + +# This is a really working version - assuming the same +# communication pattern etc. used in Trixi.jl. +function TrixiBase.mpi_isparallel() + if MPI.Initialized() + return MPI.Comm_size(MPI.COMM_WORLD) > 1 + else + return false + end +end + +end diff --git a/src/trixi_include.jl b/src/trixi_include.jl index 9ba6e9b..2fb0f6d 100644 --- a/src/trixi_include.jl +++ b/src/trixi_include.jl @@ -39,6 +39,10 @@ function trixi_include(mod::Module, elixir::AbstractString; kwargs...) find_assignment(expr, key) end + # Print information on potential wait time only in non-parallel case + if !mpi_isparallel() + @info "You just called `trixi_include`. Julia may now compile the code, please be patient." + end Base.include(ex -> replace_assignments(insert_maxiters(ex); kwargs...), mod, elixir) end @@ -143,3 +147,8 @@ function find_assignment(expr, destination) result end + +# This is just a dummy function. We only implement a real +# version if MPI.jl is loaded to avoid letting TrixiBase.jl +# depend explicitly on MPI.jl. +mpi_isparallel() = false diff --git a/test/dummy.jl b/test/dummy.jl new file mode 100644 index 0000000..f23354b --- /dev/null +++ b/test/dummy.jl @@ -0,0 +1 @@ +println("Hello") From 77c45052fd7f5ccf2385fb7bbef931a619780994 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Mon, 29 Jan 2024 16:08:26 +0100 Subject: [PATCH 2/9] fix extension including precompilation Co-authored-by: Michael Schlottke-Lakemper --- ext/TrixiBaseMPIExt.jl | 2 +- src/trixi_include.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/TrixiBaseMPIExt.jl b/ext/TrixiBaseMPIExt.jl index a99443f..b66f146 100644 --- a/ext/TrixiBaseMPIExt.jl +++ b/ext/TrixiBaseMPIExt.jl @@ -10,7 +10,7 @@ import TrixiBase # This is a really working version - assuming the same # communication pattern etc. used in Trixi.jl. -function TrixiBase.mpi_isparallel() +function TrixiBase.mpi_isparallel(::Val{:MPIExt}) if MPI.Initialized() return MPI.Comm_size(MPI.COMM_WORLD) > 1 else diff --git a/src/trixi_include.jl b/src/trixi_include.jl index 2fb0f6d..f7c0d40 100644 --- a/src/trixi_include.jl +++ b/src/trixi_include.jl @@ -40,7 +40,7 @@ function trixi_include(mod::Module, elixir::AbstractString; kwargs...) end # Print information on potential wait time only in non-parallel case - if !mpi_isparallel() + if !mpi_isparallel(Val(:MPIExt)) @info "You just called `trixi_include`. Julia may now compile the code, please be patient." end Base.include(ex -> replace_assignments(insert_maxiters(ex); kwargs...), mod, elixir) @@ -151,4 +151,4 @@ end # This is just a dummy function. We only implement a real # version if MPI.jl is loaded to avoid letting TrixiBase.jl # depend explicitly on MPI.jl. -mpi_isparallel() = false +mpi_isparallel(x) = false From 7409f27623804437b9719f90d7266903cf6ffecf Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Mon, 29 Jan 2024 16:09:58 +0100 Subject: [PATCH 3/9] precompile extension --- ext/TrixiBaseMPIExt.jl | 1 - src/trixi_include.jl | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/TrixiBaseMPIExt.jl b/ext/TrixiBaseMPIExt.jl index b66f146..ff714f6 100644 --- a/ext/TrixiBaseMPIExt.jl +++ b/ext/TrixiBaseMPIExt.jl @@ -1,6 +1,5 @@ # Package extension for adding MPI-based features to TrixiBase.jl module TrixiBaseMPIExt -__precompile__(false) # Load package extension code on Julia v1.9 and newer if isdefined(Base, :get_extension) diff --git a/src/trixi_include.jl b/src/trixi_include.jl index f7c0d40..1d823b4 100644 --- a/src/trixi_include.jl +++ b/src/trixi_include.jl @@ -40,7 +40,7 @@ function trixi_include(mod::Module, elixir::AbstractString; kwargs...) end # Print information on potential wait time only in non-parallel case - if !mpi_isparallel(Val(:MPIExt)) + if !mpi_isparallel(Val{:MPIExt}()) @info "You just called `trixi_include`. Julia may now compile the code, please be patient." end Base.include(ex -> replace_assignments(insert_maxiters(ex); kwargs...), mod, elixir) From 928da3f5885c01467f4a96c63492d585169d245e Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Mon, 29 Jan 2024 16:10:56 +0100 Subject: [PATCH 4/9] MPI compat --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index dfbbb68..50e3262 100644 --- a/Project.toml +++ b/Project.toml @@ -10,6 +10,7 @@ MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" TrixiBaseMPIExt = "MPI" [compat] +MPI = "0.20" julia = "1.8" [extras] From b5dbdea14042082e1bf867c985738a52f55967a3 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Mon, 29 Jan 2024 16:22:02 +0100 Subject: [PATCH 5/9] fix tests --- test/test_util.jl | 51 +++++++++++++++++++++++++++++++++++++++++++ test/trixi_include.jl | 10 ++++----- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/test/test_util.jl b/test/test_util.jl index 7e0912c..d79e464 100644 --- a/test/test_util.jl +++ b/test/test_util.jl @@ -20,9 +20,60 @@ macro trixi_testset(name, expr) using Test using TrixiBase + # We also include this file again to provide the definition of + # the other testing macros. This allows to use `@trixi_testset` + # in a nested fashion and also call `@test_nowarn_mod` from + # there. + include(@__FILE__) + @testset verbose=true $name $expr end nothing end end + + + +""" + @test_nowarn_mod expr + +Modified version of `@test_nowarn expr` that prints the content of `stderr` when +it is not empty and ignores some common info statements printed in Trixi.jl +uses. +""" +macro test_nowarn_mod(expr, additional_ignore_content = String[]) + quote + let fname = tempname() + try + ret = open(fname, "w") do f + redirect_stderr(f) do + $(esc(expr)) + end + end + stderr_content = read(fname, String) + if !isempty(stderr_content) + println("Content of `stderr`:\n", stderr_content) + end + + # Patterns matching the following ones will be ignored. Additional patterns + # passed as arguments can also be regular expressions, so we just use the + # type `Any` for `ignore_content`. + ignore_content = Any[# We ignore our own compilation messages + "[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.\n",] + append!(ignore_content, $additional_ignore_content) + for pattern in ignore_content + stderr_content = replace(stderr_content, pattern => "") + end + + # We also ignore simple module redefinitions for convenience. Thus, we + # check whether every line of `stderr_content` is of the form of a + # module replacement warning. + @test occursin(r"^(WARNING: replacing module .+\.\n)*$", stderr_content) + ret + finally + rm(fname, force = true) + end + end + end +end diff --git a/test/trixi_include.jl b/test/trixi_include.jl index dbd31e5..33dc748 100644 --- a/test/trixi_include.jl +++ b/test/trixi_include.jl @@ -12,11 +12,11 @@ # Use `@trixi_testset`, which wraps code in a temporary module, and call # `trixi_include` with `@__MODULE__` in order to isolate this test. - @test_nowarn trixi_include(@__MODULE__, filename) + @test_nowarn_mod trixi_include(@__MODULE__, filename) @test @isdefined x @test x == 4 - @test_nowarn trixi_include(@__MODULE__, filename, x=7) + @test_nowarn_mod trixi_include(@__MODULE__, filename, x=7) @test x == 7 @test_throws "assignment `y` not found in expression" trixi_include(@__MODULE__, @@ -79,13 +79,13 @@ # Use `@trixi_testset`, which wraps code in a temporary module, and call # `Base.include` and `trixi_include` with `@__MODULE__` in order to isolate this test. Base.include(@__MODULE__, filename1) - @test_nowarn trixi_include(@__MODULE__, filename2) + @test_nowarn_mod trixi_include(@__MODULE__, filename2) @test @isdefined x # This is the default `maxiters` inserted by `trixi_include` @test x == 10^5 - @test_nowarn trixi_include(@__MODULE__, filename2, - maxiters=7) + @test_nowarn_mod trixi_include(@__MODULE__, filename2, + maxiters=7) # Test that `maxiters` got overwritten @test x == 7 finally From 57bf100ce2df5136235e6563ae6bc274da5a5b47 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Mon, 29 Jan 2024 16:22:30 +0100 Subject: [PATCH 6/9] remove dummy test file --- test/dummy.jl | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test/dummy.jl diff --git a/test/dummy.jl b/test/dummy.jl deleted file mode 100644 index f23354b..0000000 --- a/test/dummy.jl +++ /dev/null @@ -1 +0,0 @@ -println("Hello") From 373c6cba2633f3906c89954ef6ee222644340633 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Mon, 29 Jan 2024 16:28:07 +0100 Subject: [PATCH 7/9] format --- test/test_util.jl | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/test_util.jl b/test/test_util.jl index d79e464..e1319f4 100644 --- a/test/test_util.jl +++ b/test/test_util.jl @@ -33,8 +33,6 @@ macro trixi_testset(name, expr) end end - - """ @test_nowarn_mod expr @@ -42,7 +40,7 @@ Modified version of `@test_nowarn expr` that prints the content of `stderr` when it is not empty and ignores some common info statements printed in Trixi.jl uses. """ -macro test_nowarn_mod(expr, additional_ignore_content = String[]) +macro test_nowarn_mod(expr, additional_ignore_content=String[]) quote let fname = tempname() try @@ -59,8 +57,7 @@ macro test_nowarn_mod(expr, additional_ignore_content = String[]) # Patterns matching the following ones will be ignored. Additional patterns # passed as arguments can also be regular expressions, so we just use the # type `Any` for `ignore_content`. - ignore_content = Any[# We ignore our own compilation messages - "[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.\n",] + ignore_content = Any["[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.\n"] append!(ignore_content, $additional_ignore_content) for pattern in ignore_content stderr_content = replace(stderr_content, pattern => "") @@ -72,7 +69,7 @@ macro test_nowarn_mod(expr, additional_ignore_content = String[]) @test occursin(r"^(WARNING: replacing module .+\.\n)*$", stderr_content) ret finally - rm(fname, force = true) + rm(fname, force=true) end end end From 037e34ab6cdff19c0b53e8d32b35008cdc16c22c Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 31 Jan 2024 14:06:06 +0100 Subject: [PATCH 8/9] just use at-test_nowarn_mod --- test/trixi_include.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/trixi_include.jl b/test/trixi_include.jl index 6d2ddcd..fb243d6 100644 --- a/test/trixi_include.jl +++ b/test/trixi_include.jl @@ -21,7 +21,7 @@ @test x == 7 # Verify default version (that includes in `Main`) - @test_nowarn trixi_include(filename, x = 11) + @test_nowarn_mod trixi_include(filename, x = 11) @test Main.x == 11 @test_throws "assignment `y` not found in expression" trixi_include(@__MODULE__, @@ -107,17 +107,17 @@ # This is the default `maxiters` inserted by `trixi_include` @test x == 10^5 - @test_nowarn trixi_include(@__MODULE__, filename2, - maxiters = 7) + @test_nowarn_mod trixi_include(@__MODULE__, filename2, + maxiters = 7) # Test that `maxiters` got overwritten @test x == 7 # Verify that adding `maxiters` to `maxiters` results in exactly one of them # case 1) `maxiters` is *before* semicolon in included file - @test_nowarn trixi_include(@__MODULE__, filename3, maxiters = 11) + @test_nowarn_mod trixi_include(@__MODULE__, filename3, maxiters = 11) @test y == 11 # case 2) `maxiters` is *after* semicolon in included file - @test_nowarn trixi_include(@__MODULE__, filename3, maxiters = 14) + @test_nowarn_mod trixi_include(@__MODULE__, filename3, maxiters = 14) @test y == 14 finally rm(filename1, force = true) From 8bebfd92212e11fddacda905e46da7ecabc69bdf Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 31 Jan 2024 14:06:27 +0100 Subject: [PATCH 9/9] format --- test/test_util.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_util.jl b/test/test_util.jl index e1319f4..4130cfa 100644 --- a/test/test_util.jl +++ b/test/test_util.jl @@ -40,7 +40,7 @@ Modified version of `@test_nowarn expr` that prints the content of `stderr` when it is not empty and ignores some common info statements printed in Trixi.jl uses. """ -macro test_nowarn_mod(expr, additional_ignore_content=String[]) +macro test_nowarn_mod(expr, additional_ignore_content = String[]) quote let fname = tempname() try @@ -69,7 +69,7 @@ macro test_nowarn_mod(expr, additional_ignore_content=String[]) @test occursin(r"^(WARNING: replacing module .+\.\n)*$", stderr_content) ret finally - rm(fname, force=true) + rm(fname, force = true) end end end