QMCPACK
FairDivide.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 //
10 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
11 //////////////////////////////////////////////////////////////////////////////////////
12 
13 
14 #include <cstdlib>
15 #include <tuple>
16 #include <algorithm>
17 
18 #ifndef FAIRDIVIDE_H
19 #define FAIRDIVIDE_H
20 /**@file FairDivide.h
21  *@brief A collection of functions for dividing fairly.
22  */
23 
24 /** Partition ntot over npart
25  *\param me index of boundaries being returned
26  *\param ntot the total size
27  *\param npart the number of partitions
28  *
29  *Simply divide ntot data among npart partitions so that the size of
30  *each group cannot differ by more than 1.
31  *Return the boundaries of the partition associated with partition 'me'
32  *
33  */
34 template<typename IType>
35 inline std::tuple<IType, IType> FairDivideBoundary(IType me, IType ntot, IType npart)
36 {
37  IType bat = ntot / npart;
38  IType residue = ntot % npart;
39  if (me < residue)
40  return std::make_tuple(me * (bat + 1), (me + 1) * (bat + 1));
41  else
42  return std::make_tuple(me * bat + residue, (me + 1) * bat + residue);
43 }
44 
45 /** Partition ntot over npart
46  *\param ntot the total size
47  *\param npart the number of partitions
48  *\param adist an index array
49  *
50  *Simply divide ntot data among npart partitions so that the size of
51  *each group cannot differ by more than 1.
52  *
53  *The array adist contains the offset for the i-th group,
54  *i.e., adist[i+1]-adist[i] is the number of elements for the i-th group.
55  */
56 template<class IV>
57 inline void FairDivide(int ntot, int npart, IV& adist)
58 {
59  if (adist.size() != npart + 1)
60  adist.resize(npart + 1);
61  int bat = ntot / npart;
62  int residue = ntot % npart;
63  adist[0] = 0;
64  for (int i = 1; i < npart; i++)
65  {
66  if (i < residue)
67  adist[i] = adist[i - 1] + bat + 1;
68  else
69  adist[i] = adist[i - 1] + bat;
70  }
71  adist[npart] = ntot;
72 }
73 
74 /** return the occupation vector for ntot entities partitioned npart ways.
75  */
76 template<class IV>
77 std::vector<IV> fairDivide(IV ntot, IV npart)
78 {
79  IV bat = ntot / npart;
80  IV residue = ntot % npart;
81  std::vector<IV> partitions(npart, 0);
82  std::fill_n(partitions.begin(), residue, bat + 1);
83  std::fill_n(partitions.begin() + residue, npart - residue, bat);
84  return partitions;
85 }
86 
87 /** Partition ntot over npart and the size of each partition is a multiple of base size
88  *\param ntot the total size
89  *\param base the base size
90  *\param npart the number of partitions
91  *\param me my partition id [0,ntot)
92  *\param first the beginning of my partition, can be equal and larger than ntot
93  *\param last the end of my partition, must be smaller than ntot
94  *
95  */
96 inline void FairDivideAligned(const int ntot, const int base, const int npart, const int me, int& first, int& last)
97 {
98  const int blocksize = (((ntot + npart - 1) / npart + base - 1) / base) * base;
99  first = me * blocksize;
100  last = std::min((me + 1) * blocksize, ntot);
101  if (first > last)
102  first = last;
103 }
104 
105 /** partition ntot elements among npart
106  * @param ntot total number of elements
107  * @param npart number of partitions
108  * @param adist distribution offset
109  *
110  * adist[ip-1]-adist[ip] is the number of elements of ip partition
111  * This method makes the zero-th node equal to or less than 1.
112  */
113 template<class IV>
114 inline void FairDivideLow(int ntot, int npart, IV& adist)
115 {
116  if (adist.size() != npart + 1)
117  adist.resize(npart + 1);
118  int bat = ntot / npart;
119  int residue = npart - ntot % npart;
120  adist[0] = 0;
121  for (int i = 0; i < npart; i++)
122  {
123  if (i < residue)
124  adist[i + 1] = adist[i] + bat;
125  else
126  adist[i + 1] = adist[i] + bat + 1;
127  }
128 }
129 
130 /** partition ntot elements among npart
131  * @param me rank [0,ntot)
132  * @param ntot total number of elements
133  * @param npart number of partitions
134  * @param adist distribution offset
135  * @return partition id to which me belongs
136  *
137  * mypart satisfies adist[mypart] <= me < adist[mypart+1]
138  */
139 template<class IV>
140 inline int FairDivideHigh(int me, int ntot, int npart, IV& adist)
141 {
142  if (adist.size() != npart + 1)
143  adist.resize(npart + 1);
144  int bat = ntot / npart;
145  int residue = ntot % npart;
146  int mypart = 0;
147  adist[0] = 0;
148  for (int i = 1; i < npart; i++)
149  {
150  if (i < residue)
151  adist[i] = adist[i - 1] + bat + 1;
152  else
153  adist[i] = adist[i - 1] + bat;
154  if (me >= adist[i] && me < adist[i + 1])
155  mypart = i;
156  }
157  adist[npart] = ntot;
158  return mypart;
159 }
160 
161 /** partition ntot elements among npart
162  * @param me rank [0,ntot)
163  * @param ntot total number of elements
164  * @param npart number of partitions
165  * @param adist distribution offset
166  * @return partition id to which me belongs
167  *
168  * mypart satisfies adist[mypart] <= me < adist[mypart+1]
169  */
170 template<class IV>
171 inline int FairDivideLow(int me, int ntot, int npart, IV& adist)
172 {
173  if (adist.size() != npart + 1)
174  adist.resize(npart + 1);
175  int bat = ntot / npart;
176  int residue = npart - ntot % npart;
177  int mypart = 0;
178  adist[0] = 0;
179  for (int i = 0; i < npart; i++)
180  {
181  if (i < residue)
182  adist[i + 1] = adist[i] + bat;
183  else
184  adist[i + 1] = adist[i] + bat + 1;
185  if (me >= adist[i] && me < adist[i + 1])
186  mypart = i;
187  }
188  return mypart;
189 }
190 
191 #endif
int FairDivideHigh(int me, int ntot, int npart, IV &adist)
partition ntot elements among npart
Definition: FairDivide.h:140
void fill_n(T *x, size_t count, const T &value)
Definition: OMPstd.hpp:21
T min(T a, T b)
void FairDivideLow(int ntot, int npart, IV &adist)
partition ntot elements among npart
Definition: FairDivide.h:114
void FairDivideAligned(const int ntot, const int base, const int npart, const int me, int &first, int &last)
Partition ntot over npart and the size of each partition is a multiple of base size.
Definition: FairDivide.h:96
void FairDivide(int ntot, int npart, IV &adist)
Partition ntot over npart.
Definition: FairDivide.h:57
std::tuple< IType, IType > FairDivideBoundary(IType me, IType ntot, IType npart)
Partition ntot over npart.
Definition: FairDivide.h:35
std::vector< IV > fairDivide(IV ntot, IV npart)
return the occupation vector for ntot entities partitioned npart ways.
Definition: FairDivide.h:77