3 #include "sll_assert.h"
4 #include "sll_memory.h"
5 #include "sll_working_precision.h"
15 mpi_double_precision, &
89 #define SLL_MAX_NUM_PORTS 4096
90 #define BUFFER_PADDING 4
99 sll_real64,
dimension(:),
pointer ::
data
114 sll_int32 :: other_rank = -1
115 sll_int32 :: other_port = 0
122 sll_int32 :: comm_size = 0
123 sll_int32 :: rank = -1
124 sll_int32 :: num_ports
125 sll_int32 :: buffer_size
133 #define GET_MPI_REQUEST( comm, port ) \
134 comm%ports(port)%buffer(comm%ports(port)%bit + 1)%request
147 sll_int32,
intent(in) :: port
150 'bit: ', comm%ports(port)%bit, &
151 'other_rank: ', comm%ports(port)%other_rank, &
152 'other_port: ', comm%ports(port)%other_port, &
153 'buffer(1)%data: ', comm%ports(port)%buffer(1)%data, &
154 'buffer(1)%request: ', comm%ports(port)%buffer(1)%request, &
155 'buffer(2)%data: ', comm%ports(port)%buffer(2)%data, &
156 'buffer(2)%request: ', comm%ports(port)%buffer(2)%request
161 sll_int32,
intent(in) :: bit
164 sll_assert((bit == 0) .or. (bit == 1))
168 else if (bit == 1)
then
176 sll_int32,
intent(in) :: port
179 sll_assert(
associated(comm))
181 bit = comm%ports(port)%bit
182 comm%ports(port)%bit =
flip_bit(bit)
188 sll_int32,
intent(in) :: port
190 sll_assert(
associated(comm))
195 bit = comm%ports(port)%bit
213 sll_int32 :: other_port
221 lower = ior(ishft(bit, 8), iand(my_port, int(z
'3fff', i32)))
222 higher = ior(ishft(
flip_bit(bit), 8), iand(other_port, int(z
'3fff', i32)))
228 #ifdef __INTEL_COMPILER
239 sll_int32 :: other_port
243 lower = ior(ishft(
flip_bit(bit), 8), iand(other_port, int(z
'3fff', i32)))
244 higher = ior(ishft(bit, 8), iand(my_port, int(z
'3fff', i32)))
246 send_tag = ior(ishft(higher, 15), lower)
248 #ifdef __INTEL_COMPILER
255 sll_int32,
intent(in) :: num_elems
257 sll_allocate(buff%data(num_elems + buffer_padding), ierr)
258 buff%request = mpi_request_null
263 sll_int32,
intent(in) :: buf_num_elems
265 sll_assert(buf_num_elems >= 0)
266 sll_allocate(port%buffer(2), ierr)
273 sll_int32,
intent(in) ::
size
274 sll_assert(
associated(comm))
275 if (
size > comm%buffer_size)
then
276 print *,
'comm module error, wrong size passed to check_buffer_size()'
283 sll_int32,
intent(in) :: port
284 if ((port < 1) .or. (port > comm%num_ports))
then
285 print *,
'comm module error, check_port(): ', &
286 'requested port is out of range'
294 sll_int32,
intent(in) :: port
296 sll_assert(
associated(comm))
298 if (get_mpi_request(comm, port) .ne. mpi_request_null)
then
307 sll_int32,
intent(in) :: other_rank
309 if ((other_rank < 0) .or. (other_rank >= comm%comm_size))
then
310 print *,
'comm module error, check_other_rank(): invalid remote rank'
319 sll_assert(
associated(comm))
326 sll_assert(
associated(comm))
332 sll_int32,
intent(in) :: num_ports
333 sll_int32,
intent(in) :: buffer_size
337 sll_int32 :: max_num_ports
339 if (.not.
associated(collective))
then
340 print *,
'sll_f_new_comm_real64(), passed collective pointer not associated.'
343 if (buffer_size < 0)
then
344 print *,
'sll_f_new_comm_real64(), passed negative buffer size.'
348 sll_allocate(comm, ierr)
349 comm%collective => collective
350 comm%num_ports = num_ports
353 comm%buffer_size = buffer_size
357 max_num_ports = ishft(1, 8)
359 sll_allocate(comm%ports(num_ports), ierr)
372 sll_int32,
intent(in) :: port
373 sll_int32,
intent(in) :: remote
374 sll_int32,
intent(in) :: remote_port
387 print *,
'comm module error: connect_ports(), port to connect is busy'
391 if (comm%ports(port)%other_rank >= 0)
then
392 print *,
'comm connect error; port already in use'
396 comm%ports(port)%other_rank = remote
397 comm%ports(port)%other_port = remote_port
398 bit = comm%ports(port)%bit
399 tag =
receive_tag(bit, port, comm%ports(port)%other_port)
410 comm%ports(port)%buffer(bit + 1)%data, &
411 comm%buffer_size + buffer_padding, &
412 mpi_double_precision, &
413 comm%ports(port)%other_rank, &
415 comm%collective%comm, &
416 get_mpi_request(comm, port), &
424 sll_int32,
intent(in) :: port
425 sll_int32,
intent(in) ::
size
431 if (comm%ports(port)%other_rank < 0)
then
432 print *,
'sll_s_comm_send_real64(), error, port not connected, rank = ', &
433 comm%rank,
' other_rank = ', comm%ports(port)%other_rank, &
434 ' port = ', port,
'size = ',
size
438 bit = comm%ports(port)%bit
439 tag =
send_tag(bit, port, comm%ports(port)%other_port)
447 comm%ports(port)%buffer(bit + 1)%data, &
448 size + buffer_padding, &
449 mpi_double_precision, &
450 comm%ports(port)%other_rank, &
452 comm%collective%comm, &
453 get_mpi_request(comm, port), &
455 if (ierr .ne. mpi_success)
then
456 print *,
'sll_s_comm_send_real64() error in mpi call'
465 sll_int32,
intent(in) :: port
466 sll_int32,
intent(out) :: count
467 sll_int32,
dimension(MPI_STATUS_SIZE) :: stat
470 sll_int32 :: local_count
475 print *,
'sll_s_comm_receive_real64() error: port', port,
' is not busy; ', &
476 'there are imbalanced send and receive calls.'
485 call mpi_wait(get_mpi_request(comm, port), stat, ierr)
486 if (ierr .ne. mpi_success)
then
487 print *,
'sll_s_comm_receive_real64(), MPI_Wait error'
491 call mpi_get_count(stat, mpi_double_precision, local_count, ierr)
492 if (ierr .ne. mpi_success)
then
493 print *,
'sll_s_comm_receive_real64(), MPI_Get_Count() error'
501 print *,
'sll_s_comm_receive_real64() error: imbalanced send and receive calls'
506 call mpi_wait(get_mpi_request(comm, port), mpi_status_ignore, ierr)
507 if (ierr .ne. mpi_success)
then
508 print *,
'sll_s_comm_receive_real64(), MPI_Wait error in second call.'
512 tag =
receive_tag(comm%ports(port)%bit, port, comm%ports(port)%other_port)
513 bit = comm%ports(port)%bit
516 comm%ports(port)%buffer(bit + 1)%data, &
517 comm%buffer_size + buffer_padding, &
518 mpi_double_precision, &
519 comm%ports(port)%other_rank, &
521 comm%collective%comm, &
522 get_mpi_request(comm, port), &
527 count = local_count - buffer_padding
533 sll_int32 :: num_ports
536 if (.not.
associated(comm))
then
537 print *,
'comm module error: sll_s_delete_comm_real64() received a ', &
538 'non-associated pointer argument.'
541 num_ports = comm%num_ports
547 call mpi_wait(get_mpi_request(comm, i), mpi_status_ignore, ierr)
554 call mpi_request_free(get_mpi_request(comm, i), ierr)
560 sll_deallocate(comm%ports(i)%buffer(1)%data, ierr)
561 sll_deallocate(comm%ports(i)%buffer(2)%data, ierr)
568 sll_int32,
intent(in) :: num
569 if ((num .le. 0) .or. (num .ge. sll_max_num_ports))
then
597 sll_int32,
intent(in) :: rank
598 sll_int32,
intent(in) :: nprocx
599 sll_int32,
intent(out) :: i
600 sll_int32,
intent(out) :: j
607 sll_int32,
intent(in) :: nprocx
608 sll_int32,
intent(in) :: i
609 sll_int32,
intent(in) :: j
615 sll_int32,
intent(in) :: nprocx
616 sll_int32,
intent(in) :: nprocy
626 call find_ij(rank, nprocx, iloc, jloc)
627 left = mod(iloc + nprocx - 1, nprocx)
628 right = mod(iloc + nprocx + 1, nprocx)
629 bottom = mod(jloc + nprocy - 1, nprocy)
630 top = mod(jloc + nprocy + 1, nprocy)
645 function sll_get_comm_parent(com)
647 end function sll_get_comm_parent
651 function sll_get_comm_num_ports(com)
653 end function sll_get_com_num_ports
657 function sll_get_comm_buffer_size(com)
659 end function sll_get_comm_buffer_size
685 function sll_new_comm_fan(col, root, buf_size)
687 end function sll_new_comm_fan
691 #undef SLL_MAX_NUM_PORTS
692 #undef BUFFER_PADDING
693 #undef GET_MPI_REQUEST
integer(kind=i32) function, public sll_f_get_collective_rank(col)
Determines the rank of the calling process in the communicator.
subroutine, public sll_s_collective_barrier(col)
Blocks until all processes in the communicator have reached this routine.
subroutine, public sll_s_test_mpi_error(ierr, descriptor)
Checks the good execution of collective instruction.
integer(kind=i32) function, public sll_f_get_collective_size(col)
Determines the size of the group associated with a communicator.
function send_tag(bit, my_port, other_port)
subroutine find_ij(rank, nprocx, i, j)
integer(kind=i32) function flip_bit(bit)
function get_buffer_size(comm)
logical function port_num_is_valid(num)
integer(kind=i32) function receive_tag(bit, my_port, other_port)
subroutine, public sll_s_view_port(comm, port)
subroutine flip_buffer(comm, port)
subroutine connect_ports(comm, port, remote, remote_port)
integer(kind=i32) function rank_index(nprocx, i, j)
subroutine, public sll_s_configure_comm_real64_torus_2d(comm, nprocx, nprocy)
subroutine check_port(comm, port)
subroutine initialize_buffer_real64(buff, num_elems)
function get_num_ports(comm)
subroutine initialize_port_real64(port, buf_num_elems)
real(kind=f64) function, dimension(:), pointer, public sll_f_get_buffer(comm, port)
subroutine, public sll_s_create_comm_real64_ring(comm)
subroutine, public sll_s_delete_comm_real64(comm)
subroutine, public sll_s_comm_receive_real64(comm, port, count)
logical function port_is_busy(comm, port)
subroutine check_buffer_size(comm, size)
subroutine check_other_rank(comm, other_rank)
subroutine, public sll_s_comm_send_real64(comm, port, size)
type(sll_t_p2p_comm_real64) function, pointer, public sll_f_new_comm_real64(collective, num_ports, buffer_size)
Wrapper around the communicator.