libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
thread_pool_queue_model_impl.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2014 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE { namespace ppd { namespace private_ {
20 
21 template<
22  template<class> class QM,
24  typename PTT,
25  class Pt
26 >
27 inline unsigned long __fastcall
28 thread_pool_queue_model<QM<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, Ps, PTT, Pt>::min_time(generic_traits::memory_access_modes mode) const noexcept(true) {
29  const double ws=double(this->queue().size());
30  if (ws>0.0) {
31  const pool_size_type num_threads=this->pool_size();
32  const double log_ps=std::log(static_cast<double>(num_threads));
33  const double ideal_min_time=ws/num_threads+log_ps;
36  return static_cast<unsigned long>(std::ceil(ideal_min_time));
37  } else {
38  return static_cast<unsigned long>(std::ceil(ideal_min_time*log_ps));
39  }
40  } else {
41  return 0UL;
42  }
43 }
44 
45 template<
46  template<class> class QM,
48  typename PTT,
49  class Pt
50 >
51 template<class T>
52 inline unsigned long __fastcall
53 thread_pool_queue_model<QM<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, Ps, PTT, Pt>::min_time(T const &) const noexcept(true) {
54  const double ws=double(this->queue().size());
55  if (ws>0.0) {
56  const pool_size_type num_threads=this->pool_size();
57  const double log_ps=std::log(static_cast<double>(num_threads));
58  const double ideal_min_time=ws/num_threads+log_ps;
61  return static_cast<unsigned long>(std::ceil(ideal_min_time));
62  } else {
63  return static_cast<unsigned long>(std::ceil(ideal_min_time*log_ps));
64  }
65  } else {
66  return 0UL;
67  }
68 }
69 
70 template<
71  template<class> class QM,
73  typename PTT,
74  class Pt
75 >
76 inline unsigned long __fastcall
77 thread_pool_queue_model<QM<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, Ps, PTT, Pt>::min_processors(generic_traits::memory_access_modes mode) const noexcept(true) {
78  const double ws=double(this->queue().size());
79  if (ws>0.0) {
80  const double ideal_num_processors=std::ceil(ws/std::log(ws));
83  return static_cast<unsigned long>(ideal_num_processors);
84  } else {
85  return static_cast<unsigned long>(ideal_num_processors*std::log(static_cast<double>(this->pool_size())));
86  }
87  } else {
88  return 0UL;
89  }
90 }
91 
92 template<
93  template<class> class QM,
95  typename PTT,
96  class Pt
97 >
98 template<class T>
99 inline unsigned long __fastcall
100 thread_pool_queue_model<QM<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, Ps, PTT, Pt>::min_processors(T const &) const noexcept(true) {
101  const double ws=double(this->queue().size());
102  if (ws>0.0) {
103  const double ideal_num_processors=std::ceil(ws/std::log(ws));
106  return static_cast<unsigned long>(ideal_num_processors);
107  } else {
108  return static_cast<unsigned long>(ideal_num_processors*std::log(static_cast<double>(this->pool_size())));
109  }
110  } else {
111  return 0UL;
112  }
113 }
114 
115 template<
116  template<class> class QM,
118  typename PTT,
119  class Pt
120 >
121 inline typename thread_pool_queue_model<QM<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, Ps, PTT, Pt>::queue_size_type __fastcall
122 thread_pool_queue_model<QM<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, Ps, PTT, Pt>::batch_size(queue_size_type const sz) const noexcept(true) {
123  // We need to ensure that the number of async_wk items generated is a power of two, and the number of threads in the pool may not be. So compute the next largest power of two just larger than or equal to that.
124  const pool_size_type ps=this->pool_size();
125  const double log2_ps=std::log(double(ps))/std::log(2);
126  const pool_size_type ceil_log2_ps=static_cast<pool_size_type>(std::ceil(log2_ps));
127  const pool_size_type logical_pool_size=(ceil_log2_ps==log2_ps ? ps : 1<<ceil_log2_ps);
128  return std::max(
129  static_cast<queue_size_type>(1),
130  sz/std::max(
131  logical_pool_size,
132  static_cast<pool_size_type>(1)
133  )
134  );
135 }
136 
137 template<
140  typename PTT,
141  class Pt
142 >
143 inline unsigned long __fastcall
145  const double ws=double(this->queue().size());
146  if (ws>0.0) {
147  const pool_size_type num_threads=this->pool_size();
148  const double log_ps=std::log(static_cast<double>(num_threads));
149  const double ideal_min_time=ws/num_threads+log_ps;
152  return static_cast<unsigned long>(std::ceil(ideal_min_time));
153  } else {
154  return static_cast<unsigned long>(std::ceil(ideal_min_time*log_ps));
155  }
156  } else {
157  return 0UL;
158  }
159 }
160 
161 template<
164  typename PTT,
165  class Pt
166 >
167 template<class T>
168 inline unsigned long __fastcall
169 thread_pool_queue_model<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::thread_owns_queue<SM>>, Ps, PTT, Pt>::min_time(T const &) const noexcept(true) {
170  const double ws=double(this->queue().size());
171  if (ws>0.0) {
172  const pool_size_type num_threads=this->pool_size();
173  const double log_ps=std::log(static_cast<double>(num_threads));
174  const double ideal_min_time=ws/num_threads+log_ps;
177  return static_cast<unsigned long>(std::ceil(ideal_min_time));
178  } else {
179  return static_cast<unsigned long>(std::ceil(ideal_min_time*log_ps));
180  }
181  } else {
182  return 0UL;
183  }
184 }
185 
186 template<
189  typename PTT,
190  class Pt
191 >
192 inline unsigned long __fastcall
194  const double ws=double(this->queue().size());
195  if (ws>0.0) {
196  const double ideal_num_processors=std::ceil(ws/std::log(ws));
199  return static_cast<unsigned long>(ideal_num_processors);
200  } else {
201  return static_cast<unsigned long>(ideal_num_processors*std::log(static_cast<double>(this->pool_size())));
202  }
203  } else {
204  return 0UL;
205  }
206 }
207 
208 template<
211  typename PTT,
212  class Pt
213 >
214 template<class T>
215 inline unsigned long __fastcall
217  const double ws=double(this->queue().size());
218  if (ws>0.0) {
219  const double ideal_num_processors=std::ceil(ws/std::log(ws));
222  return static_cast<unsigned long>(ideal_num_processors);
223  } else {
224  return static_cast<unsigned long>(ideal_num_processors*std::log(static_cast<double>(this->pool_size())));
225  }
226  } else {
227  return 0UL;
228  }
229 }
230 
231 template<
234  typename PTT,
235  class Pt
236 >
237 inline typename thread_pool_queue_model<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::thread_owns_queue<SM>>, Ps, PTT, Pt>::queue_size_type __fastcall
238 thread_pool_queue_model<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::thread_owns_queue<SM>>, Ps, PTT, Pt>::batch_size(queue_size_type const sz) const noexcept(true) {
239  // We need to ensure that the number of async_wk items generated is a power of two, and the number of threads in the pool may not be. So compute the next largest power of two just larger than or equal to that.
240  const pool_size_type ps=this->pool_size();
241  const double log2_ps=std::log(double(ps))/std::log(2);
242  const pool_size_type ceil_log2_ps=static_cast<pool_size_type>(std::ceil(log2_ps));
243  const pool_size_type logical_pool_size=(ceil_log2_ps==log2_ps ? ps : 1<<ceil_log2_ps);
244  return std::max(
245  static_cast<queue_size_type>(1),
246  sz/std::max(
247  logical_pool_size,
248  static_cast<pool_size_type>(1)
249  )
250  );
251 }
252 
253 template<
254  class DM1,
256  typename PTT1,
257  class Pt1
258 >
259 inline tostream &__fastcall
260 operator<<(tostream &os, thread_pool_queue_model<DM1, Ps1, PTT1, Pt1> const &t) {
261  os
262  <<static_cast<typename thread_pool_queue_model<DM1, Ps1, PTT1, Pt1>::base1_t const &>(t)
263  <<_T(", queue details: ")<<static_cast<typename thread_pool_queue_model<DM1, Ps1, PTT1, Pt1>::base_t const &>(t)
264  <<_T(", pool details: ")<<t.pool;
265  return os;
266 }
267 
268 } } } }