Neko 1.99.3
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
comm.F90
Go to the documentation of this file.
1module comm
2 use mpi_f08, only : mpi_comm, mpi_datatype, mpi_initialized, mpi_init_thread, &
3 mpi_init, mpi_thread_single, mpi_thread_funneled, &
4 mpi_thread_serialized, mpi_thread_multiple, mpi_comm_rank, &
5 mpi_comm_split, mpi_comm_dup, mpi_barrier, mpi_comm_free, mpi_finalize, &
6 mpi_comm_world, mpi_double_precision, mpi_real, mpi_comm_size
7 use utils, only : neko_error
9 use shmem
10 !$ use omp_lib
11 implicit none
12 private
13
14 interface
15 subroutine neko_comm_wrapper_init(fcomm) &
16 bind(c, name='neko_comm_wrapper_init')
17 use, intrinsic :: iso_c_binding, only : c_int
18 integer(c_int), value :: fcomm
19 end subroutine neko_comm_wrapper_init
20
21#ifdef HAVE_NVSHMEM
22 subroutine neko_comm_nvshmem_init() &
23 bind(c, name='neko_comm_nvshmem_init')
24 end subroutine neko_comm_nvshmem_init
25
26 subroutine neko_comm_nvshmem_finalize() &
27 bind(c, name='neko_comm_nvshmem_finalize')
28 end subroutine neko_comm_nvshmem_finalize
29#endif
30
31#if defined(HAVE_NCCL) || defined(HAVE_RCCL)
32 subroutine neko_comm_nccl_init() &
33 bind(c, name='neko_comm_nccl_init')
34 end subroutine neko_comm_nccl_init
35
36 subroutine neko_comm_nccl_finalize() &
37 bind(c, name='neko_comm_nccl_finalize')
38 end subroutine neko_comm_nccl_finalize
39#endif
40
41 end interface
42
43
45 type(mpi_comm), public :: neko_comm
46 type(mpi_comm), public :: neko_global_comm
47
49#ifdef HAVE_MPI_PARAM_DTYPE
50 type(mpi_datatype), public, parameter :: mpi_real_precision = mpi_double_precision
51 type(mpi_datatype), public, parameter :: mpi_extra_precision = mpi_double_precision
52#else
53 type(mpi_datatype), public :: mpi_real_precision
54 type(mpi_datatype), public :: mpi_extra_precision
55#endif
56
58 integer, public :: pe_rank
59
61 integer, public :: pe_size
62
64 logical, public :: nio
65
67 integer, public :: global_pe_rank
68
70 integer, public :: global_pe_size
71
73 integer, public :: neko_mpi_thread_provided
74
75 public :: comm_init, comm_free
76
77contains
78 subroutine comm_init
79 integer :: ierr
80 logical :: initialized
81 integer :: provided, nthrds
82 integer :: color = 0
83 integer :: envvar_len
84 character(len=255) :: color_str
85 character(len=32) :: thread_str
86 integer :: thread_envvar_len
87 integer :: requested_thread_level
88 logical :: user_thread_level
89#ifdef HAVE_OPENSHMEM
90 integer :: shmem_ierr
91 integer :: shmem_requested
92#endif
93
94 pe_rank = -1
95 pe_size = 0
96 nio = .false.
97
98 call mpi_initialized(initialized, ierr)
99
100 call get_environment_variable("NEKO_COMM_ID", color_str, envvar_len)
101 if (envvar_len .gt. 0) then
102 read(color_str(1:envvar_len), *) color
103 else
104 color = 0
105 end if
106
107 nthrds = 1
108 !$omp parallel
109 !$omp master
110 !$ nthrds = omp_get_num_threads()
111 !$omp end master
112 !$omp end parallel
113
114 call get_environment_variable("NEKO_MPI_THREAD_LEVEL", thread_str, &
115 thread_envvar_len)
116 user_thread_level = thread_envvar_len .gt. 0
117 if (user_thread_level) then
118 select case (trim(adjustl(thread_str(1:thread_envvar_len))))
119 case ("single", "SINGLE")
120 requested_thread_level = mpi_thread_single
121 case ("funneled", "FUNNELED")
122 requested_thread_level = mpi_thread_funneled
123 case ("serialized", "SERIALIZED")
124 requested_thread_level = mpi_thread_serialized
125 case ("multiple", "MULTIPLE")
126 requested_thread_level = mpi_thread_multiple
127 case default
128 call neko_error('Unknown NEKO_MPI_THREAD_LEVEL: '// &
129 trim(thread_str(1:thread_envvar_len)))
130 end select
131 end if
132
133 if (.not.initialized) then
134 if (user_thread_level) then
135 if (requested_thread_level .eq. mpi_thread_single) then
136 call mpi_init(ierr)
137 provided = mpi_thread_single
138 else
139 call mpi_init_thread(requested_thread_level, provided, ierr)
140 if (provided .lt. requested_thread_level) then
141 call neko_error('Requested MPI thread level not provided')
142 end if
143 end if
144 else if (nthrds .gt. 1) then
145 call mpi_init_thread(mpi_thread_multiple, provided, ierr)
146 if (provided .lt. mpi_thread_multiple) then
147 ! MPI_THREAD_MULTIPLE is required for mt. device backends. For
148 ! host backends the gather-scatter MPI calls are issued from the
149 ! OpenMP master thread, so MPI_THREAD_SERIALIZED (or FUNNELED) is
150 ! sufficient as a last resort.
151 if (neko_bcknd_device .eq. 1) then
152 call neko_error('Invalid thread support provided by MPI')
153 else if (provided .lt. mpi_thread_funneled) then
154 call neko_error('Invalid thread support provided by MPI')
155 end if
156 end if
157 else
158 call mpi_init(ierr)
159 end if
160 end if
161
162 neko_mpi_thread_provided = provided
163
164#ifndef HAVE_MPI_PARAM_DTYPE
165 mpi_real_precision = mpi_double_precision
166 mpi_extra_precision = mpi_double_precision
167#endif
168
169
170#ifdef HAVE_ADIOS2
171 ! We split the communicator it to work asynchronously (MPMD)
172 call mpi_comm_rank(mpi_comm_world, pe_rank, ierr)
173 call mpi_comm_split(mpi_comm_world, 0, pe_rank, neko_global_comm, ierr)
174#else
175 ! Original version duplicates the communicator:
176 call mpi_comm_dup(mpi_comm_world, neko_global_comm, ierr)
177#endif
178
179 call mpi_comm_rank(neko_global_comm, global_pe_rank, ierr)
180 call mpi_comm_size(neko_global_comm, global_pe_size, ierr)
181 if (envvar_len .gt. 0) then
182 call mpi_comm_split(neko_global_comm, color, global_pe_rank, &
183 neko_comm, ierr)
184 else
185 call mpi_comm_dup(neko_global_comm, neko_comm, ierr)
186 end if
187 call mpi_comm_rank(neko_comm, pe_rank, ierr)
188 call mpi_comm_size(neko_comm, pe_size, ierr)
189
190 ! Setup C/C++ wrapper
192
193
194#ifdef HAVE_NVSHMEM
195 ! Setup NVSHMEM (if requested)
196 call neko_comm_nvshmem_init()
197#endif
198
199#if defined(HAVE_NCCL) | defined(HAVE_RCCL)
200 ! Setup NCCL (if requested)
201 call neko_comm_nccl_init()
202#endif
203
204#ifdef HAVE_OPENSHMEM
205 ! Setup OpenSHMEM (if requested)
206 if (user_thread_level) then
207 select case (requested_thread_level)
208 case (mpi_thread_single)
209 shmem_requested = shmem_thread_single
210 case (mpi_thread_funneled)
211 shmem_requested = shmem_thread_funneled
212 case (mpi_thread_serialized)
213 shmem_requested = shmem_thread_serialized
214 case (mpi_thread_multiple)
215 shmem_requested = shmem_thread_multiple
216 end select
217 if (shmem_requested .eq. shmem_thread_single) then
218 call shmem_init()
219 else
220 shmem_ierr = shmem_init_thread(shmem_requested, provided)
221 if (provided .lt. shmem_requested) then
222 call neko_error('Requested SHMEM thread level not provided')
223 end if
224 end if
225 else if (nthrds .gt. 1) then
226 shmem_ierr = shmem_init_thread(shmem_thread_multiple, provided)
227 if (provided .ne. shmem_thread_multiple) then
228 if (neko_bcknd_device .eq. 1) then
229 call neko_error('Invalid thread support provided by SHMEM')
230 else
231 shmem_ierr = shmem_init_thread(shmem_thread_serialized, provided)
232 if (provided .ne. shmem_thread_serialized) then
233 call neko_error('Invalid thread support provided by SHMEM')
234 end if
235 end if
236 end if
237 else
238 call shmem_init()
239 end if
240#endif
241
242
243 end subroutine comm_init
244
245 subroutine comm_free
246 integer :: ierr
247
248 call mpi_barrier(neko_comm, ierr)
249 call mpi_comm_free(neko_comm, ierr)
250 call mpi_comm_free(neko_global_comm, ierr)
251
252#ifdef HAVE_NCCL
253 call neko_comm_nccl_finalize()
254#endif
255
256#ifdef HAVE_NVSHMEM
257 call neko_comm_nvshmem_finalize()
258#endif
259
260#ifdef HAVE_OPENSHMEM
261 call shmem_finalize()
262#endif
263
264 call mpi_finalize(ierr)
265
266 end subroutine comm_free
267
268end module comm
Definition comm.F90:1
subroutine, public comm_free
Definition comm.F90:246
subroutine, public comm_init
Definition comm.F90:79
logical, public nio
I/O node.
Definition comm.F90:64
type(mpi_comm), public neko_global_comm
Definition comm.F90:46
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
Definition comm.F90:53
integer, public global_pe_rank
Global MPI rank.
Definition comm.F90:67
integer, public pe_size
MPI size of communicator.
Definition comm.F90:61
integer, public pe_rank
MPI rank.
Definition comm.F90:58
integer, public global_pe_size
Global MPI size of communicator.
Definition comm.F90:70
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:45
integer, public neko_mpi_thread_provided
Thread support provided by the MPI library.
Definition comm.F90:73
type(mpi_datatype), public mpi_extra_precision
Definition comm.F90:54
Build configurations.
integer, parameter neko_bcknd_device
Fortran bindings to SHMEM's C API.
Definition shmem.F90:34
@ shmem_thread_serialized
Definition shmem.F90:56
@ shmem_thread_multiple
Definition shmem.F90:57
@ shmem_thread_single
Definition shmem.F90:54
@ shmem_thread_funneled
Definition shmem.F90:55
Utilities.
Definition utils.f90:35