Grappa  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
common.hpp
Go to the documentation of this file.
1 // This file is part of Grappa, a system for scaling irregular
3 // applications on commodity clusters.
4 
5 // Copyright (C) 2010-2014 University of Washington and Battelle
6 // Memorial Institute. University of Washington authorizes use of this
7 // Grappa software.
8 
9 // Grappa is free software: you can redistribute it and/or modify it
10 // under the terms of the Affero General Public License as published
11 // by Affero, Inc., either version 1 of the License, or (at your
12 // option) any later version.
13 
14 // Grappa is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // Affero General Public License for more details.
18 
19 // You should have received a copy of the Affero General Public
20 // License along with this program. If not, you may obtain one from
21 // http://www.affero.org/oagpl.html.
23 
25 
26 #ifndef __COMMON_HPP__
27 #define __COMMON_HPP__
28 
29 #include <stdint.h>
30 #include <iostream>
31 #include <glog/logging.h>
32 #include <memory>
33 #include <algorithm>
34 
35 using std::unique_ptr;
36 
44 template<typename T, typename... Args>
45 std::unique_ptr<T> make_unique(Args&&... args) {
46  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
47 }
48 
49 #include <cstddef>
50 using std::nullptr_t;
51 
52 #if defined(__MTA__)
53 #include <sys/mta_task.h>
54 #include <machine/runtime.h>
55 #elif defined(__MACH__)
56 #include <mach/mach_time.h>
57 #else
58 #include <time.h>
59 #endif
60 
61 #define ONE (1ULL)
62 #define KILO (1024ULL * ONE)
63 #define MEGA (1024ULL * KILO)
64 #define GIGA (1024ULL * MEGA)
65 #define TERA (1024ULL * GIGA)
66 #define PETA (1024ULL * TERA)
67 #define CACHE_LINE_SIZE (64ULL)
68 #define SIZE_OF_CACHE (MEGA * 64ULL)
69 #define THOUSAND (1000ULL * ONE)
70 #define MILLION (1000ULL * THOUSAND)
71 #define BILLION (1000ULL * MILLION)
72 
73 #ifndef MAX
74 # define MAX(a,b) ((a) < (b) ? (b) : (a))
75 #endif
76 #ifndef MIN
77 # define MIN(a,b) ((a) > (b) ? (b) : (a))
78 #endif
79 
80 // align ptr x to y boundary (rounding up)
81 #define ALIGN_UP(x, y) \
82  ((((u_int64_t)(x) & (((u_int64_t)(y))-1)) != 0) ? \
83  ((void *)(((u_int64_t)(x) & (~(u_int64_t)((y)-1)))+(y))) \
84  : ((void *)(x)))
85 
87 #define GRAPPA_DEPRECATED __attribute__((deprecated))
88 
89 namespace Grappa {
90 
92  enum class TaskMode { Bound /*default*/, Unbound };
93 
95  enum class SyncMode { Blocking /*default*/, Async };
96 
97 
99 inline double walltime(void) {
100 #if defined(__MTA__)
101  return((double)mta_get_clock(0) / mta_clock_freq());
102 #elif defined(__MACH__)
103  static mach_timebase_info_data_t info;
104  mach_timebase_info(&info);
105  uint64_t now = mach_absolute_time();
106  now *= info.numer;
107  now /= info.denom;
108  return 1.0e-9 * (double)now;
109 #else
110  struct timespec tp;
111 #if defined(CLOCK_PROCESS_CPUTIME_ID)
112 #define CLKID CLOCK_PROCESS_CPUTIME_ID
113 #elif defined(CLOCK_REALTIME_ID)
114 #define CLKID CLOCK_REALTIME_ID
115 #endif
116  clock_gettime(CLOCK_MONOTONIC, &tp);
117  return (double)tp.tv_sec + (double)tp.tv_nsec / BILLION;
118 #endif
119 }
120 
121 } // namespace Grappa
122 
123  #define GRAPPA_TIME(var, block) \
124  do { \
125  double _tmptime = Grappa::walltime(); \
126  block \
127  var = Grappa::walltime()-_tmptime; \
128  } while(0)
129 
130 #define GRAPPA_TIMER(var) \
131  for (double _tmpstart = Grappa::walltime(), _tmptime = -1; \
132  _tmptime < 0; \
133  var = _tmptime = Grappa::walltime() - _tmpstart)
134 
135 #define GRAPPA_TIME_LOG(name) \
136  for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
137  LOG(INFO) << name << ": " << (Grappa::walltime()-_tmpstart), _tmptime = 1)
138 
139 #define GRAPPA_TIME_VLOG(level, name, indent) \
140  VLOG(level) << indent << name << "..."; \
141  for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
142  VLOG(level) << indent << " (" << (Grappa::walltime()-_tmpstart) << " s)", _tmptime = 1)
143 
144 #define GRAPPA_TIME_REGION(var) \
145  for (double _tmpstart = Grappa::walltime(), _tmptime = -1; _tmptime < 0; \
146  var += (Grappa::walltime()-_tmpstart), _tmptime = 1)
147 
149 template< typename T, typename U >
150 static inline double nanless_double_ratio( T x, U y ) {
151  return y == 0 ? 0.0 : static_cast<double>(x) / static_cast<double>(y);
152 }
153 
157 #define DISALLOW_COPY_AND_ASSIGN( Name ) \
158  Name( const Name & ); \
159  void operator=( const Name & )
160 
161 namespace bittwiddle {
164  template <typename T, unsigned B>
165  inline T signextend(const T x)
166  {
167  struct {T x:B;} s;
168  return s.x = x;
169  }
170 
173  inline unsigned int log2( unsigned int v ) {
174  unsigned int r; // result of log2(v) will go here
175  unsigned int shift;
176 
177  r = (v > 0xFFFF) << 4; v >>= r;
178  shift = (v > 0xFF ) << 3; v >>= shift; r |= shift;
179  shift = (v > 0xF ) << 2; v >>= shift; r |= shift;
180  shift = (v > 0x3 ) << 1; v >>= shift; r |= shift;
181  r |= (v >> 1);
182 
183  return r;
184  }
185 }
186 
188 #define rdtscll(val) do { \
189  unsigned int __a,__d; \
190  asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
191  (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
192  } while(0)
193 
195 static inline unsigned long long rdtsc() {
196  unsigned long long val;
197  rdtscll(val);
198  return val;
199 }
200 
203 template< typename T >
205  return t;
206 }
207 
209 template< typename Container, typename Comparator >
210 auto min_element(const Container& c, Comparator cmp) -> decltype(*c.begin()) {
211  return *std::min_element(c.begin(), c.end(), cmp);
212 }
213 
215 template< typename Container, typename Comparator >
216 auto min_element(const Container& c0, const Container& c1, Comparator cmp) -> decltype(*c0.begin()) {
217  auto m0 = min_element(c0, cmp);
218  auto m1 = min_element(c1, cmp);
219  return cmp(m0,m1) ? m0 : m1;
220 }
221 
224 template< typename T >
225 struct Range { T start, end; };
226 
228 template< typename T, typename Comparator >
229 T min_element(Range<T> r, Comparator cmp) {
230  T best = r.start;
231  for (T e = r.start; e < r.end; e++) {
232  if (cmp(e,best)) {
233  best = e;
234  }
235  }
236  return best;
237 }
238 
241 
242 
243 inline std::ostream& operator<<(std::ostream& o, const range_t& r) {
244  o << "<" << r.start << "," << r.end << ">";
245  return o;
246 }
247 
248 inline range_t blockDist(int64_t start, int64_t end, int64_t rank, int64_t numBlocks) {
249  int64_t numElems = end-start;
250  int64_t each = numElems / numBlocks;
251  int64_t remain = numElems % numBlocks;
252  int64_t mynum = (rank < remain) ? each+1 : each;
253  int64_t mystart = start + ((rank < remain) ? (each+1)*rank : (each+1)*remain + (rank-remain)*each);
254  range_t r = { mystart, mystart+mynum };
255  return r;
256 }
257 
258 struct block_offset_t { int64_t block, offset; };
259 
260 inline block_offset_t indexToBlock(int64_t index, int64_t numElements, int64_t numBlocks) {
261  block_offset_t result;
262  int64_t each = numElements / numBlocks,
263  remain = numElements % numBlocks;
264  if (index < (each+1)*remain) {
265  result = { index / (each+1), index % (each+1) };
266  } else {
267  index -= (each+1)*remain;
268  result = { remain + index/each, index % each };
269  }
270  // VLOG(1) << "result.block = " << result.block << ", remain = " << remain << ", index = " << index << ", each = " << each;
271  return result;
272 }
273 
274 #define GET_TYPE(member) BOOST_PP_TUPLE_ELEM(2,0,member)
275 
276 #define GET_NAME(member) BOOST_PP_TUPLE_ELEM(2,1,member)
277 
278 #define CAT_EACH(r, data, elem) BOOST_PP_CAT(elem, data)
279 
280 #define AUTO_CONSTRUCTOR_DETAIL_PARAM(r, data, member) \
281 GET_TYPE(member) GET_NAME(member)
282 
283 #define DECL_W_TYPE(r, data, member) \
284 GET_TYPE(member) GET_NAME(member);
285 
286 #define AUTO_CONSTRUCTOR_DETAIL_INIT(r, data, member) \
287 GET_NAME(member) ( GET_NAME(member) )
288 
289 #define AUTO_CONSTRUCTOR_DETAIL(className, members) \
290 className(BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \
291 AUTO_CONSTRUCTOR_DETAIL_PARAM, BOOST_PP_EMPTY, members))) : \
292 BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM( \
293 AUTO_CONSTRUCTOR_DETAIL_INIT, BOOST_PP_EMPTY, members)) \
294 {}
295 
296 #define AUTO_CONSTRUCTOR(className, members) \
297 AUTO_CONSTRUCTOR_DETAIL(className, members)
298 
299 #define AUTO_DECLS(members) \
300 BOOST_PP_SEQ_FOR_EACH(CAT_EACH, ,BOOST_PP_SEQ_TRANSFORM(DECL_W_TYPE, BOOST_PP_EMPTY, members))
301 
302 struct Functor {
303  void operator()();
304 };
305 
306 #define FUNCTOR(name, members) \
307 struct name : public Functor { \
308 AUTO_DECLS(members) \
309 AUTO_CONSTRUCTOR( name, members ) \
310 name() {} /* default constructor */\
311 inline void operator()() const; \
312 }; \
313 inline void name::operator()() const
314 
315 
316 // fast pseudo-random number generator 0 to 32768
317 // http://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/
318 static unsigned int g_seed;
319 inline void fast_srand( int seed ) {
320  g_seed = seed;
321 }
322 inline int fast_rand() {
323  g_seed = (214013*g_seed+2531011);
324  return (g_seed>>16)&0x7FFF;
325 }
326 
327 
328 
329 namespace Grappa {
330 
333 
335  template< typename T >
336  const char * typename_of( ) {
337  // how big is the name of the type of this function?
338  static const int size = sizeof(__PRETTY_FUNCTION__);
339 
340  // make a modifiable copy that's that big
341  static char fn_name[ size ] = { '\0' };
342 
343  // copy the name into the modifiable copy
344  static const char * strcpy_retval = strncpy( fn_name, __PRETTY_FUNCTION__, size );
345 
346  // find the start of the type name
347  static const char with[] = "[with T = ";
348  static const char * name = strstr( fn_name, with ) + sizeof( with ) - 1;
349 
350  // erase the bracket at the end of the string
351  static const char erase_bracket = fn_name[size-2] = '\0';
352 
353  // whew. return the string we built.
354  return name;
355  }
356 
358  template< typename T >
359  const char * typename_of( const T& unused ) {
360  return typename_of<T>();
361  }
362 
363  namespace impl {
364  // A small helper for Google logging CHECK_NULL().
365  template <typename T>
366  inline T* CheckNull(const char *file, int line, const char *names, T* t) {
367  if (t != NULL) {
368  google::LogMessageFatal(file, line, new std::string(names));
369  }
370  return t;
371  }
372  }
373 
374 #define CHECK_NULL(val) \
375  Grappa::impl::CheckNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
376 
377 #ifdef NDEBUG
378 #define DCHECK_NULL(val) \
379  Grappa::impl::CheckNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val))
380 #else
381 #define DCHECK_NULL(val) \
382  ;
383 #endif
384 
385 
386 #define MPI_CHECK( mpi_call ) \
387  do { \
388  int retval; \
389  if( (retval = (mpi_call)) != 0 ) { \
390  char error_string[MPI_MAX_ERROR_STRING]; \
391  int length; \
392  MPI_Error_string( retval, error_string, &length); \
393  LOG(FATAL) << "MPI call failed: " #mpi_call ": " \
394  << error_string; \
395  } \
396  } while(0)
397 
399 
400 }
401 
402 namespace Grappa {
403 
406 
407 namespace impl{
408 
409 static inline void prefetcht0(const void *p) {
410  __builtin_prefetch(p, 0, 3);
411 }
412 
413 static inline void prefetchnta(const void *p) {
414  __builtin_prefetch(p, 0, 0);
415 }
416 
417 static inline void prefetcht2(const void *p) {
418  __builtin_prefetch(p, 0, 1);
419 }
420 
421 }
422 
424 
425 }
426 #endif
double walltime(void)
"Universal" wallclock time (works at least for Mac, MTA, and most Linux)
Definition: common.hpp:99
range_t blockDist(int64_t start, int64_t end, int64_t rank, int64_t numBlocks)
Definition: common.hpp:248
block_offset_t indexToBlock(int64_t index, int64_t numElements, int64_t numBlocks)
Definition: common.hpp:260
auto min_element(const Container &c, Comparator cmp) -> decltype(*c.begin())
Helper for invoking 'std::min_element' on containers.
Definition: common.hpp:210
T signextend(const T x)
Sign extension.
Definition: common.hpp:165
T end
Definition: common.hpp:225
int fast_rand()
Definition: common.hpp:322
std::unique_ptr< T > make_unique(Args &&...args)
Construct unique_ptr more easily.
Definition: common.hpp:45
SyncMode
Specify whether an operation blocks until complete, or returns "immediately".
Definition: common.hpp:95
int64_t block
Definition: common.hpp:258
T start
Definition: common.hpp:225
TaskMode
Specify whether tasks are bound to the core they're spawned on, or if they can be load-balanced (via ...
Definition: common.hpp:92
void fast_srand(int seed)
Definition: common.hpp:319
Range type that represents the values [start,end).
Definition: common.hpp:225
#define rdtscll(val)
Read 64-bit timestamp counter.
Definition: common.hpp:188
virtual const size_t size() const
Unserialized message size.
#define BILLION
Definition: common.hpp:71
const char * typename_of()
Get string containing name of type.
Definition: common.hpp:336
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:204
unsigned int log2(unsigned int v)
Base 2 log of 32-bit number.
Definition: common.hpp:173
void operator()()
std::ostream & operator<<(std::ostream &o, const range_t &r)
Definition: common.hpp:243
int64_t offset
Definition: common.hpp:258