Grappa  r3821, hash 22cd626d567a91ead5b23302066d1e9469f45c66
common.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2015, University of Washington and Battelle
3 // Memorial Institute. All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions
7 // are met:
8 // * Redistributions of source code must retain the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following
13 // disclaimer in the documentation and/or other materials
14 // provided with the distribution.
15 // * Neither the name of the University of Washington, Battelle
16 // Memorial Institute, or the names of their contributors may be
17 // used to endorse or promote products derived from this
18 // software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // UNIVERSITY OF WASHINGTON OR BATTELLE MEMORIAL INSTITUTE BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 // DAMAGE.
34 
36 
37 #ifndef __COMMON_HPP__
38 #define __COMMON_HPP__
39 
40 #include <stdint.h>
41 #include <iostream>
42 #include <glog/logging.h>
43 #include <memory>
44 #include <algorithm>
45 
46 using std::unique_ptr;
47 
55 template<typename T, typename... Args>
56 std::unique_ptr<T> make_unique(Args&&... args) {
57  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
58 }
59 
60 #include <cstddef>
61 using std::nullptr_t;
62 
63 #if defined(__MACH__)
64 #include <mach/mach_time.h>
65 #else
66 #include <time.h>
67 #endif
68 
69 #define ONE (1ULL)
70 #define KILO (1024ULL * ONE)
71 #define MEGA (1024ULL * KILO)
72 #define GIGA (1024ULL * MEGA)
73 #define TERA (1024ULL * GIGA)
74 #define PETA (1024ULL * TERA)
75 #define CACHE_LINE_SIZE (64ULL)
76 #define SIZE_OF_CACHE (MEGA * 64ULL)
77 #define THOUSAND (1000ULL * ONE)
78 #define MILLION (1000ULL * THOUSAND)
79 #define BILLION (1000ULL * MILLION)
80 
81 // align ptr x to y boundary (rounding up)
82 #define ALIGN_UP(x, y) \
83  ((((u_int64_t)(x) & (((u_int64_t)(y))-1)) != 0) ? \
84  ((void *)(((u_int64_t)(x) & (~(u_int64_t)((y)-1)))+(y))) \
85  : ((void *)(x)))
86 
88 #define GRAPPA_DEPRECATED __attribute__((deprecated))
89 
90 namespace Grappa {
91 
93  enum class TaskMode { Bound /*default*/, Unbound };
94 
96  enum class SyncMode { Blocking /*default*/, Async };
97 
98 
100 inline double walltime(void) {
101 #if defined(__MACH__)
102  static mach_timebase_info_data_t info;
103  mach_timebase_info(&info);
104  uint64_t now = mach_absolute_time();
105  now *= info.numer;
106  now /= info.denom;
107  return 1.0e-9 * (double)now;
108 #else
109  struct timespec tp;
110 #if defined(CLOCK_PROCESS_CPUTIME_ID)
111 #define CLKID CLOCK_PROCESS_CPUTIME_ID
112 #elif defined(CLOCK_REALTIME_ID)
113 #define CLKID CLOCK_REALTIME_ID
114 #endif
115  clock_gettime(CLOCK_MONOTONIC, &tp);
116  return (double)tp.tv_sec + (double)tp.tv_nsec / BILLION;
117 #endif
118 }
119 
120 } // namespace Grappa
121 
122  #define GRAPPA_TIME(var, block) \
123  do { \
124  double _tmptime = Grappa::walltime(); \
125  block \
126  var = Grappa::walltime()-_tmptime; \
127  } while(0)
128 
129 #define GRAPPA_TIMER(var) \
130  for (double _tmpstart = Grappa::walltime(), _tmptime = -1; \
131  _tmptime < 0; \
132  var = _tmptime = Grappa::walltime() - _tmpstart)
133 
134 #define GRAPPA_TIME_LOG(name) \
135  for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
136  LOG(INFO) << name << ": " << (Grappa::walltime()-_tmpstart), _tmptime = 1)
137 
138 #define GRAPPA_TIME_VLOG(level, name, indent) \
139  VLOG(level) << indent << name << "..."; \
140  for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
141  VLOG(level) << indent << " (" << (Grappa::walltime()-_tmpstart) << " s)", _tmptime = 1)
142 
143 #define GRAPPA_TIME_REGION(var) \
144  for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
145  var += (Grappa::walltime()-_tmpstart), _tmptime = 1)
146 
148 template< typename T, typename U >
149 static inline double nanless_double_ratio( T x, U y ) {
150  return y == 0 ? 0.0 : static_cast<double>(x) / static_cast<double>(y);
151 }
152 
156 #define DISALLOW_COPY_AND_ASSIGN( Name ) \
157  Name( const Name & ); \
158  void operator=( const Name & )
159 
160 namespace bittwiddle {
163  template <typename T, unsigned B>
164  inline T signextend(const T x)
165  {
166  struct {T x:B;} s;
167  return s.x = x;
168  }
169 
172  inline unsigned int log2( unsigned int v ) {
173  unsigned int r; // result of log2(v) will go here
174  unsigned int shift;
175 
176  r = (v > 0xFFFF) << 4; v >>= r;
177  shift = (v > 0xFF ) << 3; v >>= shift; r |= shift;
178  shift = (v > 0xF ) << 2; v >>= shift; r |= shift;
179  shift = (v > 0x3 ) << 1; v >>= shift; r |= shift;
180  r |= (v >> 1);
181 
182  return r;
183  }
184 }
185 
187 #define rdtscll(val) do { \
188  unsigned int __a,__d; \
189  asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
190  (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
191  } while(0)
192 
194 static inline unsigned long long rdtsc() {
195  unsigned long long val;
196  rdtscll(val);
197  return val;
198 }
199 
202 template< typename T >
204  return t;
205 }
206 
208 template< typename Container, typename Comparator >
209 auto min_element(const Container& c, Comparator cmp) -> decltype(*c.begin()) {
210  return *std::min_element(c.begin(), c.end(), cmp);
211 }
212 
214 template< typename Container, typename Comparator >
215 auto min_element(const Container& c0, const Container& c1, Comparator cmp) -> decltype(*c0.begin()) {
216  auto m0 = min_element(c0, cmp);
217  auto m1 = min_element(c1, cmp);
218  return cmp(m0,m1) ? m0 : m1;
219 }
220 
223 template< typename T >
224 struct Range { T start, end; };
225 
227 template< typename T, typename Comparator >
228 T min_element(Range<T> r, Comparator cmp) {
229  T best = r.start;
230  for (T e = r.start; e < r.end; e++) {
231  if (cmp(e,best)) {
232  best = e;
233  }
234  }
235  return best;
236 }
237 
240 
241 
242 inline std::ostream& operator<<(std::ostream& o, const range_t& r) {
243  o << "<" << r.start << "," << r.end << ">";
244  return o;
245 }
246 
247 inline range_t blockDist(int64_t start, int64_t end, int64_t rank, int64_t numBlocks) {
248  int64_t numElems = end-start;
249  int64_t each = numElems / numBlocks;
250  int64_t remain = numElems % numBlocks;
251  int64_t mynum = (rank < remain) ? each+1 : each;
252  int64_t mystart = start + ((rank < remain) ? (each+1)*rank : (each+1)*remain + (rank-remain)*each);
253  range_t r = { mystart, mystart+mynum };
254  return r;
255 }
256 
257 struct block_offset_t { int64_t block, offset; };
258 
259 inline block_offset_t indexToBlock(int64_t index, int64_t numElements, int64_t numBlocks) {
260  block_offset_t result;
261  int64_t each = numElements / numBlocks,
262  remain = numElements % numBlocks;
263  if (index < (each+1)*remain) {
264  result = { index / (each+1), index % (each+1) };
265  } else {
266  index -= (each+1)*remain;
267  result = { remain + index/each, index % each };
268  }
269  // VLOG(1) << "result.block = " << result.block << ", remain = " << remain << ", index = " << index << ", each = " << each;
270  return result;
271 }
272 
273 #define GET_TYPE(member) BOOST_PP_TUPLE_ELEM(2,0,member)
274 
275 #define GET_NAME(member) BOOST_PP_TUPLE_ELEM(2,1,member)
276 
277 #define CAT_EACH(r, data, elem) BOOST_PP_CAT(elem, data)
278 
279 #define AUTO_CONSTRUCTOR_DETAIL_PARAM(r, data, member) \
280 GET_TYPE(member) GET_NAME(member)
281 
282 #define DECL_W_TYPE(r, data, member) \
283 GET_TYPE(member) GET_NAME(member);
284 
285 #define AUTO_CONSTRUCTOR_DETAIL_INIT(r, data, member) \
286 GET_NAME(member) ( GET_NAME(member) )
287 
288 #define AUTO_CONSTRUCTOR_DETAIL(className, members) \
289 className(BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \
290 AUTO_CONSTRUCTOR_DETAIL_PARAM, BOOST_PP_EMPTY, members))) : \
291 BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \
292 AUTO_CONSTRUCTOR_DETAIL_INIT, BOOST_PP_EMPTY, members)) \
293 {}
294 
295 #define AUTO_CONSTRUCTOR(className, members) \
296 AUTO_CONSTRUCTOR_DETAIL(className, members)
297 
298 #define AUTO_DECLS(members) \
299 BOOST_PP_SEQ_FOR_EACH(CAT_EACH, ,BOOST_PP_SEQ_TRANSFORM(DECL_W_TYPE, BOOST_PP_EMPTY, members))
300 
301 struct Functor {
302  void operator()();
303 };
304 
305 #define FUNCTOR(name, members) \
306 struct name : public Functor { \
307 AUTO_DECLS(members) \
308 AUTO_CONSTRUCTOR( name, members ) \
309 name() {} /* default constructor */\
310 inline void operator()() const; \
311 }; \
312 inline void name::operator()() const
313 
314 
315 // fast pseudo-random number generator 0 to 32768
316 // http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/
317 static unsigned int g_seed;
318 inline void fast_srand( int seed ) {
319  g_seed = seed;
320 }
321 inline int fast_rand() {
322  g_seed = (214013*g_seed+2531011);
323  return (g_seed>>16)&0x7FFF;
324 }
325 
326 
327 
328 namespace Grappa {
329 
332 
334  template< typename T >
335  const char * typename_of( ) {
336  // how big is the name of the type of this function?
337  static const int size = sizeof(__PRETTY_FUNCTION__);
338 
339  // make a modifiable copy that's that big
340  static char fn_name[ size ] = { '\0' };
341 
342  // copy the name into the modifiable copy
343  static const char * strcpy_retval = strncpy( fn_name, __PRETTY_FUNCTION__, size );
344 
345  // find the start of the type name
346  static const char with[] = "[with T = ";
347  static const char * name = strstr( fn_name, with ) + sizeof( with ) - 1;
348 
349  // erase the bracket at the end of the string
350  static const char erase_bracket = fn_name[size-2] = '\0';
351 
352  // whew. return the string we built.
353  return name;
354  }
355 
357  template< typename T >
358  const char * typename_of( const T& unused ) {
359  return typename_of<T>();
360  }
361 
362  namespace impl {
363  // A small helper for Google logging CHECK_NULL().
364  template <typename T>
365  inline T* CheckNull(const char *file, int line, const char *names, T* t) {
366  if (t != NULL) {
367  google::LogMessageFatal(file, line, new std::string(names));
368  }
369  return t;
370  }
371  }
372 
373 #define CHECK_NULL(val) \
374  Grappa::impl::CheckNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
375 
376 #ifdef NDEBUG
377 #define DCHECK_NULL(val) \
378  Grappa::impl::CheckNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
379 #else
380 #define DCHECK_NULL(val) \
381  ;
382 #endif
383 
384 
385 #define MPI_CHECK( mpi_call ) \
386  do { \
387  int retval; \
388  if( (retval = (mpi_call)) != 0 ) { \
389  char error_string[MPI_MAX_ERROR_STRING]; \
390  int length; \
391  MPI_Error_string( retval, error_string, &length); \
392  LOG(FATAL) << "MPI call failed: " #mpi_call ": " \
393  << error_string; \
394  } \
395  } while(0)
396 
398 
399 }
400 
401 namespace Grappa {
402 
405 
406 namespace impl{
407 
408 static inline void prefetcht0(const void *p) {
409  __builtin_prefetch(p, 0, 3);
410 }
411 
412 static inline void prefetchnta(const void *p) {
413  __builtin_prefetch(p, 0, 0);
414 }
415 
416 static inline void prefetcht2(const void *p) {
417  __builtin_prefetch(p, 0, 1);
418 }
419 
420 }
421 
423 
424 }
425 #endif
double walltime(void)
"Universal" wallclock time (works at least for Mac, and most Linux)
Definition: common.hpp:100
range_t blockDist(int64_t start, int64_t end, int64_t rank, int64_t numBlocks)
Definition: common.hpp:247
block_offset_t indexToBlock(int64_t index, int64_t numElements, int64_t numBlocks)
Definition: common.hpp:259
auto min_element(const Container &c, Comparator cmp) -> decltype(*c.begin())
Helper for invoking 'std::min_element' on containers.
Definition: common.hpp:209
T signextend(const T x)
Sign extension.
Definition: common.hpp:164
this core's base pointer
Definition: Addressing.hpp:62
T end
Definition: common.hpp:224
int fast_rand()
Definition: common.hpp:321
std::unique_ptr< T > make_unique(Args &&...args)
Construct unique_ptr more easily.
Definition: common.hpp:56
SyncMode
Specify whether an operation blocks until complete, or returns "immediately".
Definition: common.hpp:96
int64_t block
Definition: common.hpp:257
T start
Definition: common.hpp:224
TaskMode
Specify whether tasks are bound to the core they're spawned on, or if they can be load-balanced (via ...
Definition: common.hpp:93
void fast_srand(int seed)
Definition: common.hpp:318
Range type that represents the values [start,end).
Definition: common.hpp:224
#define rdtscll(val)
Read 64-bit timestamp counter.
Definition: common.hpp:187
virtual const size_t size() const
Unserialized message size.
#define BILLION
Definition: common.hpp:79
const char * typename_of()
Get string containing name of type.
Definition: common.hpp:335
T * Grappa_magic_identity_function(T *t)
OMGWTFBBQ Grappa magic identity function Use this to get a pointer to a template function inside a te...
Definition: common.hpp:203
unsigned int log2(unsigned int v)
Base 2 log of 32-bit number.
Definition: common.hpp:172
void operator()()
std::ostream & operator<<(std::ostream &o, const range_t &r)
Definition: common.hpp:242
int64_t offset
Definition: common.hpp:257