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

Test suite clean up #3385

Open
wants to merge 55 commits into
base: master
Choose a base branch
from
Open

Test suite clean up #3385

wants to merge 55 commits into from

Conversation

JDBetteridge
Copy link
Member

@JDBetteridge JDBetteridge commented Feb 2, 2024

Description

This PR started as an experiment to "cheaply" speed up the test suite by calling mpiexec wrapping pytest, rather than forking a subprocess which calls mpiexec (which is also problematic for other reasons).

This PR now carries around multiple test suite fixes that should be merged back to master and includes fixes including:

  • Adding comm arguments to function calls that need them.
  • Freeing comms that are created.
  • Disabling a test that pollutes the tape.
  • "Fixing" ensemble parallel tests by using the simple partitioner (just in tests, Ensemble needs a proper fix!)
  • This work had to be rebased on JDBetteridge/update caching #3730 and uses PyOP2 #724 and FInAT #134 due to the deadlocks that they call.

We need to consider what aspects of this experiment we want to incorporate back into master.

Some timings for the actual speed-up (the original intention):

Results

(Real only)

Master

This week's scheduled execution:

Total (inc install): 50m 45s

This branch

With fixed caches, mpispawn, fixed FInAT hashes and pytest-split based on a timed execution.
NB: We tweak vertexonly/test_poisson_inverse_conductivity.py to only do 3 iterations (see diff)

Serial: 17m51s
2: 2m59s
3: 6m43s
4: 45s
6: 19s
7: 48s
8: 12s
Total (inc install): 46m 6s

Important, this branch only runs a maximum of 12 ranks/threads!

@connorjward
Copy link
Contributor

connorjward commented Feb 2, 2024

This is cool, but isn't it a bad idea to effectively remove test coverage? If CI doesn't run all the tests no one will.

I can see this being useful in the context of a bigger change where we run the test suite with a number of Firedrake configurations and only one of them would run these slow tests.

@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch from ecb9628 to f3685b7 Compare February 9, 2024 19:21
@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch from f3685b7 to f848c6f Compare March 5, 2024 13:40
@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch 2 times, most recently from 93a0aae to a20fc9d Compare June 7, 2024 13:52
@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch from a5f614f to 27b9af3 Compare July 19, 2024 16:25
@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch from 2a7f468 to 6ed1774 Compare August 18, 2024 13:44
@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch 2 times, most recently from 8132b64 to 1122a3b Compare August 31, 2024 18:37
@JDBetteridge JDBetteridge self-assigned this Sep 4, 2024
@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch 2 times, most recently from 9d5f056 to df4aea3 Compare September 12, 2024 13:04
Copy link

github-actions bot commented Sep 12, 2024

TestsPassed ✅Skipped ⏭️Failed ❌
Firedrake complex8094 ran6553 passed1541 skipped0 failed

Copy link

github-actions bot commented Sep 12, 2024

TestsPassed ✅Skipped ⏭️Failed ❌
Firedrake real6986 ran6542 passed427 skipped17 failed

@JDBetteridge JDBetteridge marked this pull request as ready for review September 24, 2024 14:23
@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch from bf317f5 to ef87021 Compare October 2, 2024 21:57
@connorjward connorjward changed the title Mark and skip slow tests Test suite clean up Oct 3, 2024
Copy link
Contributor

@connorjward connorjward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally very happy with this.

.github/workflows/build.yml Outdated Show resolved Hide resolved
.test_durations Outdated Show resolved Hide resolved
firedrake/parameters.py Outdated Show resolved Hide resolved
firedrake/slate/slac/compiler.py Show resolved Hide resolved
firedrake/tsfc_interface.py Outdated Show resolved Hide resolved
firedrake/tsfc_interface.py Outdated Show resolved Hide resolved
tests/demos/test_demos_run.py Outdated Show resolved Hide resolved
tests/output/test_io_mesh.py Outdated Show resolved Hide resolved
tests/slate/test_hdg_poisson.py Outdated Show resolved Hide resolved
@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch from 8435a69 to 10f7f0c Compare October 8, 2024 14:02
@JDBetteridge JDBetteridge force-pushed the JDBetteridge/faster_tests branch from 10f7f0c to f493334 Compare October 10, 2024 14:38
@JDBetteridge JDBetteridge linked an issue Oct 10, 2024 that may be closed by this pull request
.github/workflows/build.yml Show resolved Hide resolved
.github/workflows/build.yml Outdated Show resolved Hide resolved
Copy link
Contributor

@connorjward connorjward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving notes for someone (most likely me) to refer to in future. In summary:

  • Need to rebase/merge in master.
  • Tweaks to Makefile and build.yml.

-o faulthandler_timeout=1860 \
--junit-xml=firedrake2_\$MPISPAWN_TASK_ID1.xml \
-m "parallel[\$MPISPAWN_WORLD_SIZE] and not broken" \
-v tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: "dogfood" (bleh) Makefile and use a matrix to massively cut down on boilerplate

.PHONY: test_smoke
test_smoke:
@echo " Running the bare minimum smoke tests"
@python -m pytest -k "poisson_strong or stokes_mini or dg_advection" -v tests/regression/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to use MPI on the "outside" here for the parallel tests so this can be run to check things on HPC

endif
# Requires pytest and pytest-mpi only
.PHONY: test_serial
test_serial:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Terrible name! This runs all the parallel tests too!


# Requires pytest and pytest-mpi only
.PHONY: test_smoke
test_smoke:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bikeshedding: I prefer make smoke_tests or make smoketests

done

.PHONY: _test_large_world_test
_test_large_world_tests:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why we have small_world and large_world tests separately.

firedrake/slate/slac/kernel_builder.py Outdated Show resolved Hide resolved
config.addinivalue_line(
"markers",
"skipreal: mark as skipped unless in complex mode")
"broken: mark a test that is broken"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this

)
config.addinivalue_line(
"markers",
"skipcomplexnoslate: mark as skipped in complex mode due to lack of Slate"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate

config.addinivalue_line(
"markers",
"skipvtk: mark as skipped if vtk is not installed")
"skipnetgen: mark as skipped if netgen and ngsPETSc is not installed"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate

@@ -7,6 +7,7 @@
import ngsPETSc
del ngsPETSc
except ImportError:
# Netgen is not installed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Netgen is not installed

Comment on lines +120 to +121
@pytest.mark.markif_fixture(pytest.mark.slow, num_points="sparse")
@pytest.mark.markif_fixture(pytest.mark.slow, num_points="dense")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@pytest.mark.markif_fixture(pytest.mark.slow, num_points="sparse")
@pytest.mark.markif_fixture(pytest.mark.slow, num_points="dense")

@@ -321,6 +321,7 @@ def test_EquationBC_mixedpoisson_matrix_fieldsplit():
assert abs(math.log2(err[0][0]) - math.log2(err[1][0]) - (porder+1)) < 0.05


@pytest.mark.slow
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@pytest.mark.slow

@@ -231,7 +231,7 @@ def test_EquationBC_poisson_matrix(eq_type, with_bbc):
assert abs(math.log2(err[0]) - math.log2(err[1]) - (porder+1)) < 0.05


@pytest.mark.parametrize("with_bbc", [False, True])
@pytest.mark.parametrize("with_bbc", [False, pytest.param(True, marks=pytest.mark.slow)])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@pytest.mark.parametrize("with_bbc", [False, pytest.param(True, marks=pytest.mark.slow)])
@pytest.mark.parametrize("with_bbc", [False, True])

Comment on lines +27 to +29
@pytest.mark.markif_fixture(pytest.mark.slow, ipynb_file="09-hybridisation.ipynb")
@pytest.mark.markif_fixture(pytest.mark.slow, ipynb_file="10-sum-factorisation.ipynb")
@pytest.mark.markif_fixture(pytest.mark.slow, ipynb_file="12-HPC_demo.ipynb")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@pytest.mark.markif_fixture(pytest.mark.slow, ipynb_file="09-hybridisation.ipynb")
@pytest.mark.markif_fixture(pytest.mark.slow, ipynb_file="10-sum-factorisation.ipynb")
@pytest.mark.markif_fixture(pytest.mark.slow, ipynb_file="12-HPC_demo.ipynb")

Comment on lines +108 to +126
markif_fixtures = [m for m in item.own_markers if m.name == "markif_fixture"]
for mark in markif_fixtures:
'''@pytest.mark.markif_fixture(*marks, **conditions)
marks: str | pytest.mark.structures.Mark
marks to apply if conditions are met
conditions: dict
dictionary of conditions; consisting of function argument keys
and fixture values or ids
'''
# (function argument names, fixture ids) in a list
fixtures = [(name, id_) for name, id_ in zip(item.callspec.params.keys(), item.callspec._idlist)]
# If all the fixtures are in the dictionary of conditions apply all of the marks
if all((k, str(v)) in fixtures for k, v in mark.kwargs.items()):
for label in mark.args:
if isinstance(label, str):
item.add_marker(getattr(pytest.mark, label)())
else:
item.add_marker(label())

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
markif_fixtures = [m for m in item.own_markers if m.name == "markif_fixture"]
for mark in markif_fixtures:
'''@pytest.mark.markif_fixture(*marks, **conditions)
marks: str | pytest.mark.structures.Mark
marks to apply if conditions are met
conditions: dict
dictionary of conditions; consisting of function argument keys
and fixture values or ids
'''
# (function argument names, fixture ids) in a list
fixtures = [(name, id_) for name, id_ in zip(item.callspec.params.keys(), item.callspec._idlist)]
# If all the fixtures are in the dictionary of conditions apply all of the marks
if all((k, str(v)) in fixtures for k, v in mark.kwargs.items()):
for label in mark.args:
if isinstance(label, str):
item.add_marker(getattr(pytest.mark, label)())
else:
item.add_marker(label())

Comment on lines +13 to +16
config.addinivalue_line(
"markers",
"slow: mark a test that takes a while to run"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove

@JDBetteridge
Copy link
Member Author

Why would you remove the slow markers? They are really useful if you want to run the test suite faster (especially in parallel!) and are also there to highlight tests that can be sped up.

@connorjward
Copy link
Contributor

Why would you remove the slow markers?

Sorry to undo your hard work but I don't see the benefit in having them:

They are really useful if you want to run the test suite faster (especially in parallel!)

But it doesn't run all of the tests. It is useful to be able to run only a few fast tests (a la make check) but I can't imagine a situation where I would want to run most-but-not-all of the tests.

and are also there to highlight tests that can be sped up.

We already know which tests are slow from .test_durations and from the

============================ slowest 200 durations =============================

output from pytest. This is another source of truth and I think it will immediately bit-rot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

INSTALL: Tests not passing on fresh install M2 Mac
4 participants