-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathabstract_load_balancer.f90
More file actions
126 lines (109 loc) · 4.91 KB
/
abstract_load_balancer.f90
File metadata and controls
126 lines (109 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
module SLB4MPI_abstract_load_balancer_m
#ifdef SLB4MPI_WITH_MPI
use mpi
#endif
implicit none
private
#ifndef SLB4MPI_WITH_MPI
integer, parameter :: MPI_INTEGER_KIND = 4
integer, parameter :: MPI_ADDRESS_KIND = 8
#endif
public :: MPI_INTEGER_KIND
public :: MPI_ADDRESS_KIND
integer, parameter, public :: BITS_IN_BYTE = 8
type, abstract :: load_balancer_t
integer(MPI_INTEGER_KIND) :: communicator !< MPI communicator
integer(MPI_INTEGER_KIND) :: rank !< Rank of the process
integer(MPI_INTEGER_KIND) :: root = 0 !< Rank of the root process
integer(MPI_INTEGER_KIND) :: nranks !< Number of processes (group size)
integer(8) :: lower_bound !< Lower bound of range
integer(8) :: upper_bound !< Upper bound of range
integer(8) :: min_chunk_size !< Minimal chunk size for job
integer(8) :: max_chunk_size !< Maximal chunk size for job
contains
procedure(initialize), deferred, public :: initialize
procedure(get_range), deferred, public :: get_range
procedure(clean), deferred, public :: clean
procedure :: default_initialize
end type load_balancer_t
abstract interface
!>
!> @brief initialize load balancer
!>
!> @param[in,out] lb - load balancer object
!> @param[in] communicator - MPI communicator on which load balancer will be used
!> @param[in] lower_bound - lower bound of range
!> @param[in] upper_bound - upper bound of range, upper_bound >= lower_bound
!> @param[in] min_chunk_size - minimal size of chank that can be associated with job, default: 1
!> @param[in] max_chunk_size - maximal size of chank that can be associated with job, default: upper_bound - lower_bound + 1
!>
subroutine initialize(lb, communicator, lower_bound, upper_bound, min_chunk_size, max_chunk_size)
import load_balancer_t, MPI_INTEGER_KIND
class(load_balancer_t), intent(inout) :: lb
integer(MPI_INTEGER_KIND), intent(in) :: communicator
integer(8), intent(in) :: lower_bound, upper_bound
integer(8), optional, intent(in) :: min_chunk_size, max_chunk_size
end subroutine initialize
!>
!> @brief get range to compute
!>
!> @note `upper_bound` can be only less than or equal `load_balancer_t%upper_bound`.
!> So, for last elements a batch with size less than `min_chunk_size` can be returned
!>
!> @param[in,out] lb - load balancer object
!> @param[out] lower_bound - lower bound of range to compute
!> @param[out] upper_bound - upper bound of range to compute
!> @return - true if there is something to compute
!>
logical function get_range(lb, lower_bound, upper_bound)
import load_balancer_t
class(load_balancer_t), intent(inout) :: lb
integer(8), intent(out) :: lower_bound, upper_bound
end function get_range
!>
!> @brief load balancer destructor
!>
!> @param[in,out] lb - load balancer object
!>
subroutine clean(lb)
import load_balancer_t
class(load_balancer_t), intent(inout) :: lb
end subroutine clean
end interface
public :: load_balancer_t
contains
!>
!> @brief initialize variables of load balancer with default values
!>
!> @param[in,out] lb - load balancer object
!> @param[in] communicator - MPI communicator on which load balancer will be used
!> @param[in] lower_bound - lower bound of range
!> @param[in] upper_bound - upper bound of range, upper_bound >= lower_bound
!> @param[in] min_chunk_size - minimal size of chank that can be associated with job, default: 1
!> @param[in] max_chunk_size - maximal size of chank that can be associated with job, default: upper_bound - lower_bound + 1
!>
subroutine default_initialize(lb, communicator, lower_bound, upper_bound, min_chunk_size, max_chunk_size)
class(load_balancer_t), intent(inout) :: lb
integer(MPI_INTEGER_KIND), intent(in) :: communicator
integer(8), intent(in) :: lower_bound, upper_bound
integer(8), optional, intent(in) :: min_chunk_size, max_chunk_size
integer(MPI_INTEGER_KIND) :: ierr
#ifdef SLB4MPI_WITH_MPI
call MPI_Comm_rank(communicator, lb%rank, ierr)
call MPI_Comm_size(communicator, lb%nranks, ierr)
#else
lb%rank = 0
lb%nranks = 1
#endif
lb%communicator = communicator
lb%lower_bound = lower_bound
lb%upper_bound = upper_bound
lb%min_chunk_size = 1
if (present(min_chunk_size)) lb%min_chunk_size = min_chunk_size
lb%max_chunk_size = max((lb%upper_bound - lb%lower_bound + 1) / lb%nranks, lb%min_chunk_size)
if (present(max_chunk_size)) lb%max_chunk_size = max_chunk_size
if (lb%min_chunk_size <= 0) error stop "Min chunk size must be greater than zero!"
if (lb%lower_bound > lb%upper_bound) error stop "Upper bound is less than lower bound!"
if (lb%min_chunk_size > lb%max_chunk_size) error stop "Max chunk size is less than min chunk size!"
end subroutine default_initialize
end module SLB4MPI_abstract_load_balancer_m