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

Mpi omp support #14

Merged
merged 27 commits into from
Aug 16, 2024
Merged

Mpi omp support #14

merged 27 commits into from
Aug 16, 2024

Conversation

hiker
Copy link
Owner

@hiker hiker commented Aug 2, 2024

Adds support for specifying MPI and OpenMP in the config file.

@hiker
Copy link
Owner Author

hiker commented Aug 2, 2024

This patch is not 'as big' as it appears to be - because of adding parameters to BuildConfig, they had to be added to a lot of files and examples. Additionally, I addressed coding style issues as suggested by Matthew recently (max 80 characters/line). Note that the MPI based compiler classes are not proper wrapper yet, they will be re-implemented in the next PR.

@hiker
Copy link
Owner Author

hiker commented Aug 8, 2024

Quick explanation:
the idea of this PR is that the user defines in the BuildConfig if the build is to be done with MPI, and with OpenMP (they are not exclusive). This means that the ToolRepository can pick an appropriate compiler by default (if the user doesn't specify what compiler they want), which solves e.g. the problem that e.g. ifort is being picked as default for an intel-based build (instead of an Intel based MPI wrapper). ATM we hard-code this still in the script.
The support for OpenMP means that the compiler can select its own (compiler-specific) OpenMP flags. ATM we have these flags hard-coded in the scripts.

source/fab/tools/compiler.py Show resolved Hide resolved
@@ -59,6 +61,9 @@ def get_tool(self, category: Category) -> Tool:
return self._all_tools[category]

# No tool was specified for this category, get the default tool
# from the ToolRepository:
# from the ToolRepository, and at it, so we don't need to look
Copy link
Collaborator

Choose a reason for hiding this comment

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

and at it

do you mean "and add it"?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Indeed.

tests/unit_tests/tools/test_compiler.py Show resolved Hide resolved
assert mpi_gfortran.name == "mpif90-gfortran"
assert isinstance(mpi_gfortran, FortranCompiler)
assert mpi_gfortran.category == Category.FORTRAN_COMPILER
assert mpi_gfortran.mpi

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we need a test of get_version() on the mpi compilers, to make sure we fixed the issue Jason found

Copy link
Owner Author

Choose a reason for hiding this comment

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

I've parameterised all the valid compiler version tests to test both the compiler and mpi wrapper.

Copy link
Owner Author

Choose a reason for hiding this comment

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

In hindsight a stupid idea of me. The next PR (compiler wrapper) refactors the MPI* wrapper and creates their own file with their own tests, so I had to remove the parameterisation in the next PR again. The 'future' compiler wrapper do explicitly test that the wrapper and the wrapper compiler report the same version :(

# Notice that "-J/b" has been removed
fc.run.assert_called_with(cwd=PosixPath('.'),
additional_parameters=['-c', "-O3",
'-J', '/module_out',
'a.f90', '-o', 'a.o'])
with pytest.warns(UserWarning,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd prefer this to be a separate test, but it at least needs a comment. Currently you have to play spot-the-difference with the code above 😀

Copy link
Owner Author

Choose a reason for hiding this comment

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

Done ... I think.

tests/unit_tests/tools/test_linker.py Show resolved Hide resolved
source/fab/tools/tool_box.py Show resolved Hide resolved
@@ -164,9 +184,20 @@ def build_output(self) -> Path:
'''
return self.project_workspace / BUILD_OUTPUT

@property
def mpi(self) -> bool:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are these properties (BuildConfig.mpi and BuildConfig.openmp) used in you later tickets? Right now I can't see if they do anything. Couldn't I create a BuildConfig(mpi=False) and still use it with mpi?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Good catch. MPI was used in compile_c, but not compile_fortran (and as previously discussed, we don't raise an exception if you request MPI and a non-MPI compiler is already loaded, based on the idea that the user knows what they are doing). I am thinking more and more that we should raise an exception in this case :(
Openmp is used in both compile_c and ..._fortran

# the key being tool.suite != suite --> all tools with the right
# suite use False as key, all other tools True. Since False < True
# this results in all suite tools to be at the front of the list
self[category] = sorted(self[category],
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this assume add_tool is never called after set_default_compiler_suite? That might be fine, I can't tell

Copy link
Owner Author

Choose a reason for hiding this comment

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

Not really. ATM I use this (in the NCI setup) to first pick our default suite (intel-classic), then add additional compilers (tau-wrapper around ifort) to the repository. This way the default will still remain the plain ifort (or mpi wrapper around ifort), while the tau ones (which are all of the same suite 'intel-classic') are available if a user wants to pick them, but they will not be picked by default.

Actually, now that I think about it, the order doesn't matter. Fab will first add the 'standard' compiler (e.g. ifort, mpif90-ifort), and whenever the default is changed, a stable-sort is called, so ifort/mpif90-ifort will be before any user added tool.

@hiker
Copy link
Owner Author

hiker commented Aug 14, 2024

I hope I've addressed all issues. Ready for next review.

@hiker hiker requested a review from lukehoffmann August 14, 2024 13:51
source/fab/tools/compiler.py Show resolved Hide resolved
source/fab/tools/tool_box.py Show resolved Hide resolved
@lukehoffmann lukehoffmann merged commit 83836e7 into bom_master Aug 16, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants