Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,13 @@

# IntelliJ
.idea/
cmake-build-*/
cmake-build-*/

# Build Dirs
build/

# Build Artifact
*.dylib
*.a
*.mod
*.o
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ include_directories("${CMAKE_SOURCE_DIR}/src")
set(SOURCE_CODE
src/mpilib20.F90
src/routines/mpilib20_init_finalise.F90
src/routines/mpilib20_reduce.F90
src/bindings/mpi_bindings.F90
src/errors_warnings/asserts.F90
PARENT_SCOPE
Expand Down
12 changes: 8 additions & 4 deletions src/bindings/mpi_bindings.F90
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ module mpi_bindings
MPI_FINALIZE, &
MPI_COMM_SIZE, &
MPI_GROUP_SIZE, &
MPI_REDUCE, &

! Data types
MPI_COMM_WORLD, &
MPI_THREAD_SINGLE, &
MPI_THREAD_FUNNELED, &
MPI_THREAD_SERIALIZED, &
MPI_THREAD_MULTIPLE, &
MPI_INTEGER, &

! Derived types
MPI_Comm, &
Expand Down Expand Up @@ -57,13 +59,15 @@ module mpi_bindings
MPI_FINALIZE, &
MPI_COMM_SIZE, &
MPI_GROUP_SIZE, &
MPI_REDUCE, &

! Data types
MPI_COMM_WORLD, &
MPI_THREAD_SINGLE, &
MPI_THREAD_FUNNELED, &
MPI_COMM_WORLD, &
MPI_THREAD_SINGLE, &
MPI_THREAD_FUNNELED, &
MPI_THREAD_SERIALIZED, &
MPI_THREAD_MULTIPLE
MPI_THREAD_MULTIPLE, &
MPI_INTEGER

implicit none
public
Expand Down
23 changes: 23 additions & 0 deletions src/routines/generic_templates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generic Subroutine Templates
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated
Store templates for the most generic form of a subroutine to be overloaded. Allowing rapid replication.

## MPI_REDUCE
```fortran
!> MPI_REDUCE WRAPPER: INTEGER
subroutine mpilib20_reduce_type(sendbuf, recvbuf, op, root, mpi_env)
use mpi_bindings, only : MPI_REDUCE, MPI_Op, &
MPI_TYPE
!> Variable containing set to be sent
type(MPI_TYPE), intent(in) :: sendbuf
!> Variable to receive reduced set
type(MPI_TYPE), intent(inout) :: recvbuf
!> MPI Operation
type(MPI_Op), intent(in) :: op
!> Rank of the process to receive the reduced set
integer, intent(in) :: root
!> Instance of the MPI environment
type(mpi_env_type), intent(inout) :: mpi_env

call MPI_REDUCE(sendbuf, recvbuf, 1, MPI_TYPE, op, root, mpi_env%comm, mpi_env%ierror)
end subroutine mpilib20_reduce_type
````
83 changes: 83 additions & 0 deletions src/routines/mpilib20_reduce.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
!> Wrapping of the MPI_REDUCE methods
!> TODOs
!> Unravel how MPI_Datatype operates
!> Overload for MPI_IN_PLACE?
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I'm not entirely sure how MPI_IN_PLACE works. For a single communicator, it's a pointless operation. Once they're split, we'd need to consider its use

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

MPI_IN_PLACE is actually quite complicated to overload - MPI_IN_PLACE replaces sendbuf for the root process (indicating that the sendbuf and recvbuf are the same) BUT on non-root processes, there needs to be a variable passed via sendbuf. Not sure what this means for overloading for when sendbuf is MPI_IN_PLACE, probably would have MPI_IN_PLACE as an optional logical with logic to ensure correct filling of the (in this case) sendbuf and recvbuf variables for MPI_REDUCE.

https://stackoverflow.com/questions/17741574/in-place-mpi-reduce-crashes-with-openmpi

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Ok, makes sense to ignore in the first instance and add an issue to address. I've never needed to use personally and only seen it recently

  • Create issue

!> Testing
module mpilib20_reduce_m

use mpilib20_init_finalise, only : mpi_env_type

implicit none

private

interface mpilib20_reduce
module procedure mpilib20_reduce_int_scalar
module procedure mpilib20_reduce_int_vec
end interface

public :: mpilib20_REDUCE
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated

contains

!> MPI_REDUCE WRAPPER: INTEGER
subroutine mpilib20_reduce_int_scalar(sendbuf, recvbuf, operation, mpi_env, root)
use mpi_bindings, only : MPI_REDUCE, MPI_Op, &
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated
MPI_Datatype, MPI_INTEGER
use mpilib20_init_finalise, only : root_id
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated
!> Variable containing set to be sent
type(MPI_Datatype), intent(in) :: sendbuf
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated
!> Variable to receive reduced set
type(MPI_Datatype), intent(inout) :: recvbuf
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I'm guessing this wants to be intent(out) as it shouldn't come in with a value

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

For arrays, I assume intent(inout) is required as this will have to be preallocated?

!> MPI Operation
type(MPI_Op), intent(in) :: operation
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

We don't want to pass the operation. This should be inferable from the input data type.

Copy link
Copy Markdown
Collaborator Author

@maxwilliams94 maxwilliams94 Feb 20, 2021

Choose a reason for hiding this comment

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

How would MPI_MAX and MPI_MIN be infered? Same with MPI_PRODUCT and MPI_SUM?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Good point. I think we could make operation optional and have default behaviour as sum. My feeling is the majority of use cases are sum. Would also be easy to change.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

  • make operation optional and have sum as default.

!> Instance of the MPI environment
type(mpi_env_type), intent(inout) :: mpi_env
!> Rank of the process to receive the reduced set (override default)
integer, optional, intent(in) :: root
integer :: use_root
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated

!> Overide root process if passed
if (present(root)) then
use_root = root
else
use_root = root_id
end if

call MPI_REDUCE(sendbuf, recvbuf, 1, MPI_INTEGER, operation, use_root, mpi_env%comm, mpi_env%ierror)

end subroutine mpilib20_reduce_int_scalar

!> MPI_REDUCE WRAPPER: INTEGER(:)
!> Rank 1 arrays don't require flattening
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated
subroutine mpilib20_reduce_int_vec(sendbuf, recvbuf, operation, mpi_env, root)
use mpi_bindings, only : MPI_REDUCE, MPI_Op, &
MPI_Datatype, MPI_INTEGER
use mpilib20_init_finalise, only : root_id
!> Variable containing set to be sent
type(MPI_Datatype), intent(in) :: sendbuf(:)
!> Variable to receive reduced set
type(MPI_Datatype), intent(inout) :: recvbuf(:)
!> MPI Operation
type(MPI_Op), intent(in) :: operation
!> Instance of the MPI environment
type(mpi_env_type), intent(inout) :: mpi_env
!> Rank of the process to receive the reduced set (override default)
integer, optional, intent(in) :: root
integer :: count
integer :: use_root

!> Overide root process if passed
if (present(root)) then
use_root = root
else
use_root = root_id
end if
!> Element count based-on receiving buffer size
count = size(recvbuf)
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated

call MPI_REDUCE(sendbuf, recvbuf, count, MPI_INTEGER, operation, root, mpi_env%comm, mpi_env%ierror)
Comment thread
maxwilliams94 marked this conversation as resolved.
Outdated

end subroutine mpilib20_reduce_int_vec

end module mpilib20_reduce_m