Octopus
states_elec_all_to_all_communications.F90
Go to the documentation of this file.
1!! Copyright (C) 2023 N. Tancogne-Dejean
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21
32 use accel_oct_m
33 use batch_oct_m
34 use debug_oct_m
35 use global_oct_m
36 use math_oct_m
37 use mesh_oct_m
39 use mpi_oct_m
45
46 implicit none
47
48 private
49
50 public :: &
52
54 private
55
56 integer :: task_from
57 integer :: task_to
58
59 integer :: nbatch_to_receive
60 integer :: nbatch_to_send
61 integer :: n_comms
62
63 integer :: nblock_to_receive
64 integer :: nblock_to_send
65
66 logical :: gpu_aware = .false.
67
68 type(MPI_Request), allocatable :: send_req(:)
69 contains
74 procedure :: alloc_receive_batch => states_elec_all_to_all_communications_alloc_receive_batch
75 procedure :: get_send_indices => states_elec_all_to_all_communications_get_send_indices
76 procedure :: get_receive_indices => states_elec_all_to_all_communications_get_receive_indices
77 procedure :: dpost_all_mpi_isend => dstates_elec_all_to_all_communications_post_all_mpi_isend
78 procedure :: zpost_all_mpi_isend => zstates_elec_all_to_all_communications_post_all_mpi_isend
79 procedure :: spost_all_mpi_isend => sstates_elec_all_to_all_communications_post_all_mpi_isend
80 procedure :: cpost_all_mpi_isend => cstates_elec_all_to_all_communications_post_all_mpi_isend
85 procedure :: disend_batch_to => dstates_elec_all_to_all_communications_isend_batch_to
86 procedure :: zisend_batch_to => zstates_elec_all_to_all_communications_isend_batch_to
87 procedure :: dmpi_irecv_batch => dstates_elec_all_to_all_communications_mpi_irecv_batch
88 procedure :: zmpi_irecv_batch => zstates_elec_all_to_all_communications_mpi_irecv_batch
89 procedure :: sisend_batch_to => sstates_elec_all_to_all_communications_isend_batch_to
90 procedure :: cisend_batch_to => cstates_elec_all_to_all_communications_isend_batch_to
91 procedure :: smpi_irecv_batch => sstates_elec_all_to_all_communications_mpi_irecv_batch
92 procedure :: cmpi_irecv_batch => cstates_elec_all_to_all_communications_mpi_irecv_batch
93 procedure :: drecv_batch_from => dstates_elec_all_to_all_communications_recv_batch_from
94 procedure :: zrecv_batch_from => zstates_elec_all_to_all_communications_recv_batch_from
95 procedure :: srecv_batch_from => sstates_elec_all_to_all_communications_recv_batch_from
96 procedure :: crecv_batch_from => cstates_elec_all_to_all_communications_recv_batch_from
97 procedure :: wait_all_isend => states_elec_all_to_all_communications_wait_all_isend
99
100contains
101
102 !------------------------------------------------------------
106 subroutine states_elec_all_to_all_communications_start(this, st, task_from, task_to, gpu_aware)
107 class(states_elec_all_to_all_communications_t), intent(inout) :: this
108 type(states_elec_t), intent(in) :: st
109 integer, intent(in) :: task_from, task_to
110 logical, optional, intent(in) :: gpu_aware
111
113
114 this%task_from = task_from
115 this%task_to = task_to
116
117 this%gpu_aware = optional_default(gpu_aware, .false.)
118
119 this%nbatch_to_receive = states_elec_all_to_all_communications_eval_nreceive(st, task_from, this%nblock_to_receive)
120 this%nbatch_to_send = states_elec_all_to_all_communications_eval_nsend(st, task_to, this%nblock_to_send)
121
122 !Number of communications
123 this%n_comms = max(this%nbatch_to_send, this%nbatch_to_receive)
124
127
128 !------------------------------------------------------------
130 integer function states_elec_all_to_all_communications_eval_nreceive(st, task_from, nblock_to_receive) result(nbatch_to_receive)
131 type(states_elec_t), intent(in) :: st
132 integer, intent(in) :: task_from
133 integer, intent(out) :: nblock_to_receive
134
135 integer :: st_start, st_end, kpt_start, kpt_end, ib
136
138
139 nbatch_to_receive = 0
140 nblock_to_receive = 0
141
142 !What we receive for the wfn
143 if (task_from > -1) then
144 st_start = st%st_kpt_task(task_from, 1)
145 st_end = st%st_kpt_task(task_from, 2)
146 kpt_start = st%st_kpt_task(task_from, 3)
147 kpt_end = st%st_kpt_task(task_from, 4)
149 nblock_to_receive = 0
150 do ib = 1, st%group%nblocks
151 if (st%group%block_range(ib, 1) >= st_start .and. st%group%block_range(ib, 2) <= st_end) then
152 nblock_to_receive = nblock_to_receive + 1
153 end if
154 end do
155 nbatch_to_receive = nblock_to_receive * (kpt_end-kpt_start+1)
156 end if
157
158 write(message(1), '(a,i5,a,i5,a,i5)') 'Debug: Task ', st%st_kpt_mpi_grp%rank, ' will receive ', &
159 nbatch_to_receive, ' batches from task ', task_from
160 call messages_info(1, all_nodes=.true., debug_only=.true.)
164
165 !------------------------------------------------------------
167 integer function states_elec_all_to_all_communications_eval_nsend(st, task_to, nblock_to_send) result(nbatch_to_send)
168 type(states_elec_t), intent(in) :: st
169 integer, intent(in) :: task_to
170 integer, intent(out) :: nblock_to_send
174 nbatch_to_send = 0
175 nblock_to_send = 0
177 if (task_to > -1) then
178 nblock_to_send = (st%group%block_end-st%group%block_start+1)
179 nbatch_to_send = nblock_to_send*(st%d%kpt%end-st%d%kpt%start+1)
180 end if
182 write(message(1), '(a,i5,a,i5,a,i5)') 'Debug: Task ', st%st_kpt_mpi_grp%rank, ' will send ', nbatch_to_send, &
183 ' batches to task ', task_to
184 call messages_info(1, all_nodes=.true., debug_only=.true.)
189 !------------------------------------------------------------
191 integer pure function states_elec_all_to_all_communications_get_ncom(this) result(n_comms)
193
194 n_comms = this%n_comms
196
197 !------------------------------------------------------------
199 integer pure function states_elec_all_to_all_communications_get_nreceive(this) result(nbatch_to_receive)
200 class(states_elec_all_to_all_communications_t), intent(in) :: this
202 nbatch_to_receive = this%nbatch_to_receive
204
205 !------------------------------------------------------------
207 integer pure function states_elec_all_to_all_communications_get_nsend(this) result(nbatch_to_send)
208 class(states_elec_all_to_all_communications_t), intent(in) :: this
209
210 nbatch_to_send = this%nbatch_to_send
212
213 !------------------------------------------------------------
215 subroutine states_elec_all_to_all_communications_alloc_receive_batch(this, st, icom, np, psib)
216 class(states_elec_all_to_all_communications_t), intent(in) :: this
217 type(states_elec_t), intent(in) :: st
218 integer, intent(in) :: icom
219 integer, intent(in) :: np
220 type(wfs_elec_t), intent(out) :: psib
221
222 integer :: block_id, ib, ik
223
226 ! Given the icom, returns the id of the block of state communicated
227 block_id = mod(icom-1, this%nblock_to_receive)+1
228 ik = int((icom-block_id)/this%nblock_to_receive) + st%st_kpt_task(this%task_from, 3)
229 ib = block_id - 1 + st%group%iblock(st%st_kpt_task(this%task_from, 1))
230
231 write(message(1), '(a,i5,a,i5,a,i5)') 'Debug: Task ', st%st_kpt_mpi_grp%rank, ' allocates memory for block ', &
232 ib, ' and k-point ', ik
233 call messages_info(1, all_nodes=.true., debug_only=.true.)
234
235 call states_elec_parallel_allocate_batch(st, psib, np, ib, ik, packed=.true.)
236
237 ! For CUDA-aware MPI, the batch must be on GPU to receive directly in the buffer.
238 if (this%gpu_aware) then
239 call psib%do_pack(batch_device_packed, copy = .false.)
240 end if
241
244
245 !------------------------------------------------------------
247 subroutine states_elec_all_to_all_communications_get_send_indices(this, st, icom, ib, ik)
248 class(states_elec_all_to_all_communications_t), intent(in) :: this
249 type(states_elec_t), intent(in) :: st
250 integer, intent(in) :: icom
251 integer, intent(out) :: ib
252 integer, intent(out) :: ik
253
255
256 ! Given the icom, returns the id of the block of state communicated
257 ib = mod(icom-1, this%nblock_to_send) + 1
258 ik = int((icom-ib)/this%nblock_to_send) + st%d%kpt%start
259 ib = ib - 1 + st%group%iblock(st%st_start)
260
261 write(message(1), '(a,i5,a,i5,a,i5)') 'Debug: Task ', st%st_kpt_mpi_grp%rank, ' will send the block ', &
262 ib, ' with k-point ', ik
263 call messages_info(1, all_nodes=.true., debug_only=.true.)
264
267
268 !------------------------------------------------------------
270 subroutine states_elec_all_to_all_communications_get_receive_indices(this, st, icom, ib, ik)
271 class(states_elec_all_to_all_communications_t), intent(in) :: this
272 type(states_elec_t), intent(in) :: st
273 integer, intent(in) :: icom
274 integer, intent(out) :: ib
275 integer, intent(out) :: ik
276
278
279 ! Given the icom, returns the id of the block of state communicated
280 ib = mod(icom-1, this%nblock_to_receive)+1
281 ik = int((icom-ib)/this%nblock_to_receive) + st%st_kpt_task(this%task_from, 3)
282 ib = ib - 1 + st%group%iblock(st%st_kpt_task(this%task_from, 1))
283
284 if (debug%info) then
285 write(message(1), '(a,i5,a,i5,a,i5)') 'Task ', st%st_kpt_mpi_grp%rank, ' will receive the block ', &
286 ib, ' with k-point ', ik
287 call messages_info(1, all_nodes=.true.)
288 end if
289
292
293 !------------------------------------------------------------
296 class(states_elec_all_to_all_communications_t), intent(inout) :: this
297 type(states_elec_t), intent(in) :: st
298
300 call profiling_in("ALL_TO_ALL_COMM")
301
302 if (allocated(this%send_req)) then
303
304 call st%st_kpt_mpi_grp%wait(this%nbatch_to_send, this%send_req)
305
306 safe_deallocate_a(this%send_req)
307
308 end if
309
310 call profiling_out("ALL_TO_ALL_COMM")
313
314
315
316#include "undef.F90"
317#include "real.F90"
318#include "states_elec_all_to_all_communications_inc.F90"
319
320#include "undef.F90"
321#include "complex.F90"
322#include "states_elec_all_to_all_communications_inc.F90"
323
324#include "undef.F90"
325#include "real32.F90"
326#include "states_elec_all_to_all_communications_inc.F90"
327
328#include "undef.F90"
329#include "complex32.F90"
330#include "states_elec_all_to_all_communications_inc.F90"
331#include "undef.F90"
332
334
335!! Local Variables:
336!! mode: f90
337!! coding: utf-8
338!! End:
This module implements batches of mesh functions.
Definition: batch.F90:135
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
This module provides routines for communicating all batches in a ring-pattern scheme.
subroutine states_elec_all_to_all_communications_get_receive_indices(this, st, icom, ib, ik)
Given the icom step, returns the block and k-point indices to be received.
subroutine sstates_elec_all_to_all_communications_isend_batch_to(this, st, np, psib, node_to, icom, send_req)
Post a single MPI isend for an explicit batch to node_to.
integer function states_elec_all_to_all_communications_eval_nsend(st, task_to, nblock_to_send)
How many batches we will send from task_send.
subroutine zstates_elec_all_to_all_communications_isend_batch_to(this, st, np, psib, node_to, icom, send_req)
Post a single MPI isend for an explicit batch to node_to.
subroutine zstates_elec_all_to_all_communications_mpi_irecv_batch(this, st, np, node_fr, icom, psib_receiv, recv_req)
Allocate a batch and post the MPI_Irecv for it. The caller must wait on recv_req before using the bat...
subroutine sstates_elec_all_to_all_communications_mpi_irecv_batch(this, st, np, node_fr, icom, psib_receiv, recv_req)
Allocate a batch and post the MPI_Irecv for it. The caller must wait on recv_req before using the bat...
subroutine states_elec_all_to_all_communications_wait_all_isend(this, st)
Do a MPI waitall for the isend requests.
subroutine zstates_elec_all_to_all_communications_post_all_mpi_isend(this, st, np, node_to)
Post all isend commands for all batches of a given task.
integer pure function states_elec_all_to_all_communications_get_nreceive(this)
Returns the number of receiv calls.
subroutine sstates_elec_all_to_all_communications_recv_batch_from(this, st, np, psib, node_fr, icom)
Blocking MPI recv into an already-allocated batch from node_fr.
subroutine cstates_elec_all_to_all_communications_isend_batch_to(this, st, np, psib, node_to, icom, send_req)
Post a single MPI isend for an explicit batch to node_to.
subroutine states_elec_all_to_all_communications_alloc_receive_batch(this, st, icom, np, psib)
Given the icom step, allocate the receiv buffer (wfs_elec_t)
subroutine dstates_elec_all_to_all_communications_isend_batch(this, st, np, ib_send, ik_send, node_to, icom, send_req)
Post a single MPI isend for the batch (ib_send, ik_send) to node_to.
integer pure function states_elec_all_to_all_communications_get_ncom(this)
Returns the number of communications.
subroutine cstates_elec_all_to_all_communications_recv_batch_from(this, st, np, psib, node_fr, icom)
Blocking MPI recv into an already-allocated batch from node_fr.
subroutine dstates_elec_all_to_all_communications_post_all_mpi_isend(this, st, np, node_to)
Post all isend commands for all batches of a given task.
subroutine states_elec_all_to_all_communications_get_send_indices(this, st, icom, ib, ik)
Given the icom step, returns the block and k-point indices to be sent.
subroutine cstates_elec_all_to_all_communications_post_all_mpi_isend(this, st, np, node_to)
Post all isend commands for all batches of a given task.
subroutine cstates_elec_all_to_all_communications_mpi_irecv_batch(this, st, np, node_fr, icom, psib_receiv, recv_req)
Allocate a batch and post the MPI_Irecv for it. The caller must wait on recv_req before using the bat...
integer function states_elec_all_to_all_communications_eval_nreceive(st, task_from, nblock_to_receive)
How many batches we will receive from task_from.
subroutine states_elec_all_to_all_communications_start(this, st, task_from, task_to, gpu_aware)
Given a task to send to, and a task to receive from, initializes a states_elec_all_to_all_communicati...
subroutine sstates_elec_all_to_all_communications_isend_batch(this, st, np, ib_send, ik_send, node_to, icom, send_req)
Post a single MPI isend for the batch (ib_send, ik_send) to node_to.
subroutine dstates_elec_all_to_all_communications_mpi_irecv_batch(this, st, np, node_fr, icom, psib_receiv, recv_req)
Allocate a batch and post the MPI_Irecv for it. The caller must wait on recv_req before using the bat...
subroutine cstates_elec_all_to_all_communications_isend_batch(this, st, np, ib_send, ik_send, node_to, icom, send_req)
Post a single MPI isend for the batch (ib_send, ik_send) to node_to.
subroutine zstates_elec_all_to_all_communications_recv_batch_from(this, st, np, psib, node_fr, icom)
Blocking MPI recv into an already-allocated batch from node_fr.
subroutine sstates_elec_all_to_all_communications_post_all_mpi_isend(this, st, np, node_to)
Post all isend commands for all batches of a given task.
subroutine dstates_elec_all_to_all_communications_isend_batch_to(this, st, np, psib, node_to, icom, send_req)
Post a single MPI isend for an explicit batch to node_to.
integer pure function states_elec_all_to_all_communications_get_nsend(this)
Returns the number send calls.
subroutine dstates_elec_all_to_all_communications_recv_batch_from(this, st, np, psib, node_fr, icom)
Blocking MPI recv into an already-allocated batch from node_fr.
subroutine zstates_elec_all_to_all_communications_isend_batch(this, st, np, ib_send, ik_send, node_to, icom, send_req)
Post a single MPI isend for the batch (ib_send, ik_send) to node_to.
This module provides routines for communicating states when using states parallelization.
The states_elec_t class contains all electronic wave functions.
int true(void)