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 :: process_receives => states_elec_all_to_all_communications_process_receives
75 procedure :: process_sends => states_elec_all_to_all_communications_process_sends
76 procedure :: alloc_receive_batch => states_elec_all_to_all_communications_alloc_receive_batch
77 procedure :: get_send_indices => states_elec_all_to_all_communications_get_send_indices
78 procedure :: get_receive_indices => states_elec_all_to_all_communications_get_receive_indices
79 procedure :: dpost_all_mpi_isend => dstates_elec_all_to_all_communications_post_all_mpi_isend
80 procedure :: zpost_all_mpi_isend => zstates_elec_all_to_all_communications_post_all_mpi_isend
81 procedure :: spost_all_mpi_isend => sstates_elec_all_to_all_communications_post_all_mpi_isend
82 procedure :: cpost_all_mpi_isend => cstates_elec_all_to_all_communications_post_all_mpi_isend
87 procedure :: disend_batch_to => dstates_elec_all_to_all_communications_isend_batch_to
88 procedure :: zisend_batch_to => zstates_elec_all_to_all_communications_isend_batch_to
89 procedure :: dmpi_irecv_batch => dstates_elec_all_to_all_communications_mpi_irecv_batch
90 procedure :: zmpi_irecv_batch => zstates_elec_all_to_all_communications_mpi_irecv_batch
91 procedure :: sisend_batch_to => sstates_elec_all_to_all_communications_isend_batch_to
92 procedure :: cisend_batch_to => cstates_elec_all_to_all_communications_isend_batch_to
93 procedure :: smpi_irecv_batch => sstates_elec_all_to_all_communications_mpi_irecv_batch
94 procedure :: cmpi_irecv_batch => cstates_elec_all_to_all_communications_mpi_irecv_batch
95 procedure :: drecv_batch_from => dstates_elec_all_to_all_communications_recv_batch_from
96 procedure :: zrecv_batch_from => zstates_elec_all_to_all_communications_recv_batch_from
97 procedure :: srecv_batch_from => sstates_elec_all_to_all_communications_recv_batch_from
98 procedure :: crecv_batch_from => cstates_elec_all_to_all_communications_recv_batch_from
99 procedure :: wait_all_isend => states_elec_all_to_all_communications_wait_all_isend
101
102contains
103
107 subroutine states_elec_all_to_all_communications_start(this, st, task_from, task_to, gpu_aware)
108 class(states_elec_all_to_all_communications_t), intent(inout) :: this
109 type(states_elec_t), intent(in) :: st
110 integer, intent(in) :: task_from, task_to
111 logical, optional, intent(in) :: gpu_aware
112
113 integer :: kpt_start, kpt_end
114
116
117 this%task_from = task_from
118 this%task_to = task_to
119
120 this%gpu_aware = optional_default(gpu_aware, .false.)
121
122 !What we receive for the wfn
123 this%nblock_to_receive = set_nblock_to_receive(st, task_from)
124 this%nbatch_to_receive = 0
125 if (task_from > -1) then
126 kpt_start = st%st_kpt_task(task_from, 3)
127 kpt_end = st%st_kpt_task(task_from, 4)
128 this%nbatch_to_receive = this%nblock_to_receive * (kpt_end - kpt_start + 1)
129 end if
130
131 write(message(1), '(a,i5,a,i5,a,i5)') 'Debug: Task ', st%st_kpt_mpi_grp%rank, ' will receive ', &
132 this%nbatch_to_receive, ' batches from task ', task_from
133 call messages_info(1, all_nodes=.true., debug_only=.true.)
134
135 !What we send for the wfn
136 this%nblock_to_send = merge(st%group%block_end - st%group%block_start + 1, 0, task_to > -1)
137 this%nbatch_to_send = this%nblock_to_send * (st%d%kpt%end - st%d%kpt%start + 1)
138
139 write(message(1), '(a,i5,a,i5,a,i5)') 'Debug: Task ', st%st_kpt_mpi_grp%rank, ' will send ', &
140 this%nbatch_to_send, ' batches to task ', task_to
141 call messages_info(1, all_nodes=.true., debug_only=.true.)
142
143 !Number of communications
144 this%n_comms = max(this%nbatch_to_send, this%nbatch_to_receive)
145
149 ! Private free function
150
152 function set_nblock_to_receive(st, task_from) result(nblock_to_receive)
153 type(states_elec_t), intent(in) :: st
154 integer, intent(in) :: task_from
155 integer :: nblock_to_receive
157 integer :: st_start, st_end, ib
160
161 nblock_to_receive = 0
162
163 if (task_from > -1) then
164 st_start = st%st_kpt_task(task_from, 1)
165 st_end = st%st_kpt_task(task_from, 2)
166 nblock_to_receive = 0
167 do ib = 1, st%group%nblocks
168 if (st%group%block_range(ib, 1) >= st_start .and. st%group%block_range(ib, 2) <= st_end) then
169 nblock_to_receive = nblock_to_receive + 1
170 end if
171 end do
172 end if
178 ! Type-bound member functions
180 !------------------------------------------------------------
182 integer pure function states_elec_all_to_all_communications_get_ncom(this) result(n_comms)
185 n_comms = this%n_comms
188 !------------------------------------------------------------
190 integer pure function states_elec_all_to_all_communications_get_nreceive(this) result(nbatch_to_receive)
193 nbatch_to_receive = this%nbatch_to_receive
195
196 !------------------------------------------------------------
198 integer pure function states_elec_all_to_all_communications_get_nsend(this) result(nbatch_to_send)
199 class(states_elec_all_to_all_communications_t), intent(in) :: this
200
201 nbatch_to_send = this%nbatch_to_send
203
204 !------------------------------------------------------------
206 logical pure function states_elec_all_to_all_communications_process_receives(this, icom) result(receives)
207 class(states_elec_all_to_all_communications_t), intent(in) :: this
208 integer, intent(in) :: icom
209
210 receives = this%task_from > -1 .and. icom <= this%nbatch_to_receive
212
213 !------------------------------------------------------------
215 logical pure function states_elec_all_to_all_communications_process_sends(this, icom) result(sends)
216 class(states_elec_all_to_all_communications_t), intent(in) :: this
217 integer, intent(in) :: icom
218
219 sends = this%task_to > -1 .and. icom <= this%nbatch_to_send
221
222 !------------------------------------------------------------
224 subroutine states_elec_all_to_all_communications_alloc_receive_batch(this, st, icom, np, psib)
225 class(states_elec_all_to_all_communications_t), intent(in) :: this
226 type(states_elec_t), intent(in) :: st
227 integer, intent(in) :: icom
228 integer, intent(in) :: np
229 type(wfs_elec_t), intent(out) :: psib
230
231 integer :: block_id, ib, ik
232
234
235 ! Given the icom, returns the id of the block of state communicated
236 block_id = mod(icom-1, this%nblock_to_receive)+1
237 ik = int((icom-block_id)/this%nblock_to_receive) + st%st_kpt_task(this%task_from, 3)
238 ib = block_id - 1 + st%group%iblock(st%st_kpt_task(this%task_from, 1))
239
240 write(message(1), '(a,i5,a,i5,a,i5)') 'Debug: Task ', st%st_kpt_mpi_grp%rank, ' allocates memory for block ', &
241 ib, ' and k-point ', ik
242 call messages_info(1, all_nodes=.true., debug_only=.true.)
243
244 call states_elec_parallel_allocate_batch(st, psib, np, ib, ik, packed=.true.)
245
246 ! For CUDA-aware MPI, the batch must be on GPU to receive directly in the buffer.
247 if (this%gpu_aware) then
248 call psib%do_pack(batch_device_packed, copy = .false.)
249 end if
250
253
254 !------------------------------------------------------------
256 subroutine states_elec_all_to_all_communications_get_send_indices(this, st, icom, ib, ik)
257 class(states_elec_all_to_all_communications_t), intent(in) :: this
258 type(states_elec_t), intent(in) :: st
259 integer, intent(in) :: icom
260 integer, intent(out) :: ib
261 integer, intent(out) :: ik
262
264
265 ! Given the icom, returns the id of the block of state communicated
266 ib = mod(icom-1, this%nblock_to_send) + 1
267 ik = int((icom-ib)/this%nblock_to_send) + st%d%kpt%start
268 ib = ib - 1 + st%group%iblock(st%st_start)
269
270 write(message(1), '(a,i5,a,i5,a,i5)') 'Debug: Task ', st%st_kpt_mpi_grp%rank, ' will send the block ', &
271 ib, ' with k-point ', ik
272 call messages_info(1, all_nodes=.true., debug_only=.true.)
273
276
277 !------------------------------------------------------------
279 subroutine states_elec_all_to_all_communications_get_receive_indices(this, st, icom, ib, ik)
280 class(states_elec_all_to_all_communications_t), intent(in) :: this
281 type(states_elec_t), intent(in) :: st
282 integer, intent(in) :: icom
283 integer, intent(out) :: ib
284 integer, intent(out) :: ik
287
288 ! Given the icom, returns the id of the block of state communicated
289 ib = mod(icom-1, this%nblock_to_receive)+1
290 ik = int((icom-ib)/this%nblock_to_receive) + st%st_kpt_task(this%task_from, 3)
291 ib = ib - 1 + st%group%iblock(st%st_kpt_task(this%task_from, 1))
292
293 if (debug%info) then
294 write(message(1), '(a,i5,a,i5,a,i5)') 'Task ', st%st_kpt_mpi_grp%rank, ' will receive the block ', &
295 ib, ' with k-point ', ik
296 call messages_info(1, all_nodes=.true.)
297 end if
298
302 !------------------------------------------------------------
305 class(states_elec_all_to_all_communications_t), intent(inout) :: this
306 type(states_elec_t), intent(in) :: st
307
309 call profiling_in("ALL_TO_ALL_COMM")
311 if (allocated(this%send_req)) then
312 call st%st_kpt_mpi_grp%wait(this%nbatch_to_send, this%send_req)
313 safe_deallocate_a(this%send_req)
314 end if
315
316 call profiling_out("ALL_TO_ALL_COMM")
320
321#include "undef.F90"
322#include "real.F90"
323#include "states_elec_all_to_all_communications_inc.F90"
324
325#include "undef.F90"
326#include "complex.F90"
327#include "states_elec_all_to_all_communications_inc.F90"
328
329#include "undef.F90"
330#include "real32.F90"
331#include "states_elec_all_to_all_communications_inc.F90"
332
333#include "undef.F90"
334#include "complex32.F90"
335#include "states_elec_all_to_all_communications_inc.F90"
336#include "undef.F90"
337
339
340!! Local Variables:
341!! mode: f90
342!! coding: utf-8
343!! 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.
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 an 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.
logical pure function states_elec_all_to_all_communications_process_receives(this, icom)
Returns true if communication step icom receives a batch from task_from.
integer function set_nblock_to_receive(st, task_from)
How many blocks we will receive from task_from.
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...
logical pure function states_elec_all_to_all_communications_process_sends(this, icom)
Returns true if communication step icom sends a batch to task_to.
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)