Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LargeArray.h
Go to the documentation of this file.
1 /*
2  * This file belongs to the Galois project, a C++ library for exploiting
3  * parallelism. The code is being released under the terms of the 3-Clause BSD
4  * License (a copy is located in LICENSE.txt at the top-level directory).
5  *
6  * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
7  * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
8  * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
10  * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
11  * DEALING OR USAGE OF TRADE. NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
12  * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
13  * shall University be liable for incidental, special, indirect, direct or
14  * consequential damages or loss of profits, interruption of business, or
15  * related expenses which may arise from use of Software or Documentation,
16  * including but not limited to those resulting from defects in Software and/or
17  * Documentation, or loss or inaccuracy of data of any kind.
18  */
19 
20 #ifndef GALOIS_LARGEARRAY_H
21 #define GALOIS_LARGEARRAY_H
22 
23 #include <iostream>
24 #include <utility>
25 
26 #include <boost/archive/binary_iarchive.hpp>
27 #include <boost/archive/binary_oarchive.hpp>
28 #include <boost/serialization/binary_object.hpp>
29 #include <boost/serialization/array.hpp>
30 #include <boost/serialization/serialization.hpp>
31 #include <boost/serialization/split_member.hpp>
32 
33 #include "galois/config.h"
34 #include "galois/Galois.h"
35 #include "galois/gIO.h"
36 #include "galois/ParallelSTL.h"
37 #include "galois/runtime/Mem.h"
39 
40 namespace galois {
41 
42 namespace runtime {
43 extern unsigned activeThreads;
44 } // end namespace runtime
45 
52 template <typename T>
53 class LargeArray {
54  substrate::LAptr m_realdata;
55  T* m_data;
56  size_t m_size;
57 
58 public:
59  typedef T raw_value_type;
60  typedef T value_type;
61  typedef size_t size_type;
62  typedef ptrdiff_t difference_type;
64  typedef const value_type& const_reference;
65  typedef value_type* pointer;
66  typedef const value_type* const_pointer;
67  typedef pointer iterator;
69  const static bool has_value = true;
70 
71  // Extra indirection to support incomplete T's
72  struct size_of {
73  const static size_t value = sizeof(T);
74  };
75 
76 protected:
79  assert(!m_data);
80  m_size = n;
81  switch (t) {
82  case Blocked:
83  galois::gDebug("Block-alloc'd");
84  m_realdata =
86  break;
87  case Interleaved:
88  galois::gDebug("Interleave-alloc'd");
89  m_realdata = substrate::largeMallocInterleaved(n * sizeof(T),
91  break;
92  case Local:
93  galois::gDebug("Local-allocd");
94  m_realdata = substrate::largeMallocLocal(n * sizeof(T));
95  break;
96  case Floating:
97  galois::gDebug("Floating-alloc'd");
98  m_realdata = substrate::largeMallocFloating(n * sizeof(T));
99  break;
100  };
101  m_data = reinterpret_cast<T*>(m_realdata.get());
102  }
103 
104 private:
105  /*
106  * To support boost serialization
107  */
108  friend class boost::serialization::access;
109  template <typename Archive>
110  void save(Archive& ar, const unsigned int) const {
111 
112  // TODO DON'T USE CERR
113  // std::cerr << "save m_size : " << m_size << " Threads : " <<
114  // runtime::activeThreads << "\n";
115  ar << m_size;
116  // for(size_t i = 0; i < m_size; ++i){
117  // ar << m_data[i];
118  //}
119  ar << boost::serialization::make_binary_object(m_data, m_size * sizeof(T));
120  /*
121  * Cas use make_array too as shown below
122  * IMPORTANT: Use make_array as temp fix for benchmarks using non-trivial
123  * structures in nodeData (Eg. SGD) This also requires changes in
124  * libgalois/include/galois/graphs/Details.h (specified in the file).
125  */
126  // ar << boost::serialization::make_array<T>(m_data, m_size);
127  }
128  template <typename Archive>
129  void load(Archive& ar, const unsigned int) {
130  ar >> m_size;
131 
132  // TODO DON'T USE CERR
133  // std::cerr << "load m_size : " << m_size << " Threads : " <<
134  // runtime::activeThreads << "\n";
135 
136  // TODO: For now, always use allocateInterleaved
137  // Allocates and sets m_data pointer
138  if (!m_data)
139  allocateInterleaved(m_size);
140 
141  // for(size_t i = 0; i < m_size; ++i){
142  // ar >> m_data[i];
143  //}
144  ar >> boost::serialization::make_binary_object(m_data, m_size * sizeof(T));
145  /*
146  * Cas use make_array too as shown below
147  * IMPORTANT: Use make_array as temp fix for SGD
148  * This also requires changes in
149  * libgalois/include/galois/graphs/Details.h (specified in the file).
150  */
151  // ar >> boost::serialization::make_array<T>(m_data, m_size);
152  }
153  // The macro BOOST_SERIALIZATION_SPLIT_MEMBER() generates code which invokes
154  // the save or load depending on whether the archive is used for saving or
155  // loading
156  BOOST_SERIALIZATION_SPLIT_MEMBER()
157 
158 public:
162  LargeArray(void* d, size_t s) : m_data(reinterpret_cast<T*>(d)), m_size(s) {}
163 
164  LargeArray() : m_data(0), m_size(0) {}
165 
166  LargeArray(LargeArray&& o) : m_data(0), m_size(0) {
167  std::swap(this->m_realdata, o.m_realdata);
168  std::swap(this->m_data, o.m_data);
169  std::swap(this->m_size, o.m_size);
170  }
171 
173  std::swap(this->m_realdata, o.m_realdata);
174  std::swap(this->m_data, o.m_data);
175  std::swap(this->m_size, o.m_size);
176  return *this;
177  }
178 
179  LargeArray(const LargeArray&) = delete;
180  LargeArray& operator=(const LargeArray&) = delete;
181 
183  destroy();
184  deallocate();
185  }
186 
187  friend void swap(LargeArray& lhs, LargeArray& rhs) {
188  std::swap(lhs.m_realdata, rhs.m_realdata);
189  std::swap(lhs.m_data, rhs.m_data);
190  std::swap(lhs.m_size, rhs.m_size);
191  }
192 
193  const_reference at(difference_type x) const { return m_data[x]; }
194  reference at(difference_type x) { return m_data[x]; }
195  const_reference operator[](size_type x) const { return m_data[x]; }
196  reference operator[](size_type x) { return m_data[x]; }
197  void set(difference_type x, const_reference v) { m_data[x] = v; }
198  size_type size() const { return m_size; }
199  iterator begin() { return m_data; }
200  const_iterator begin() const { return m_data; }
201  iterator end() { return m_data + m_size; }
202  const_iterator end() const { return m_data + m_size; }
203 
207 
214 
221 
228 
239  template <typename RangeArrayTy>
240  void allocateSpecified(size_type numberOfElements,
241  RangeArrayTy& threadRanges) {
242  assert(!m_data);
243 
244  m_realdata = substrate::largeMallocSpecified(numberOfElements * sizeof(T),
246  threadRanges, sizeof(T));
247 
248  m_size = numberOfElements;
249  m_data = reinterpret_cast<T*>(m_realdata.get());
250  }
252 
253  template <typename... Args>
254  void construct(Args&&... args) {
255  for (T *ii = m_data, *ei = m_data + m_size; ii != ei; ++ii)
256  new (ii) T(std::forward<Args>(args)...);
257  }
258 
259  template <typename... Args>
260  void constructAt(size_type n, Args&&... args) {
261  new (&m_data[n]) T(std::forward<Args>(args)...);
262  }
263 
265  template <typename... Args>
266  void create(size_type n, Args&&... args) {
268  construct(std::forward<Args>(args)...);
269  }
270 
271  void deallocate() {
272  m_realdata.reset();
273  m_data = 0;
274  m_size = 0;
275  }
276 
277  void destroy() {
278  if (!m_data)
279  return;
280  galois::ParallelSTL::destroy(m_data, m_data + m_size);
281  }
282 
283  template <typename U = T>
284  std::enable_if_t<!std::is_scalar<U>::value> destroyAt(size_type n) {
285  (&m_data[n])->~T();
286  }
287 
288  template <typename U = T>
289  std::enable_if_t<std::is_scalar<U>::value> destroyAt(size_type) {}
290 
291  // The following methods are not shared with void specialization
292  const_pointer data() const { return m_data; }
293  pointer data() { return m_data; }
294 };
295 
297 template <>
298 class LargeArray<void> {
299 
300 private:
301  /*
302  * To support boost serialization
303  * Can use single function serialize instead of save and load, since both save
304  * and load have identical code.
305  */
306  friend class boost::serialization::access;
307  template <typename Archive>
308  void serialize(Archive&, const unsigned int) const {}
309 
310 public:
311  LargeArray(void*, size_t) {}
312  LargeArray() = default;
313  LargeArray(const LargeArray&) = delete;
314  LargeArray& operator=(const LargeArray&) = delete;
315 
316  friend void swap(LargeArray&, LargeArray&) {}
317 
318  typedef void raw_value_type;
319  typedef void* value_type;
320  typedef size_t size_type;
321  typedef ptrdiff_t difference_type;
324  typedef value_type* pointer;
326  typedef pointer iterator;
328  const static bool has_value = false;
329  struct size_of {
330  const static size_t value = 0;
331  };
332 
333  const_reference at(difference_type) const { return 0; }
334  reference at(difference_type) { return 0; }
335  const_reference operator[](size_type) const { return 0; }
336  template <typename AnyTy>
337  void set(difference_type, AnyTy) {}
338  size_type size() const { return 0; }
339  iterator begin() { return 0; }
340  const_iterator begin() const { return 0; }
341  iterator end() { return 0; }
342  const_iterator end() const { return 0; }
343 
346  void allocateLocal(size_type, bool = true) {}
348  template <typename RangeArrayTy>
349  void allocateSpecified(size_type, RangeArrayTy) {}
350 
351  template <typename... Args>
352  void construct(Args&&...) {}
353  template <typename... Args>
354  void constructAt(size_type, Args&&...) {}
355  template <typename... Args>
356  void create(size_type, Args&&...) {}
357 
358  void deallocate() {}
359  void destroy() {}
361 
362  const_pointer data() const { return 0; }
363  pointer data() { return 0; }
364 };
365 
366 } // namespace galois
367 #endif
void destroy()
Definition: LargeArray.h:359
size_type size() const
Definition: LargeArray.h:338
void set(difference_type x, const_reference v)
Definition: LargeArray.h:197
friend void swap(LargeArray &lhs, LargeArray &rhs)
Definition: LargeArray.h:187
LAptr largeMallocBlocked(size_t bytes, unsigned numThreads)
Definition: NumaMem.cpp:188
void destroyAt(size_type)
Definition: LargeArray.h:360
void raw_value_type
Definition: LargeArray.h:318
void destroy()
Definition: LargeArray.h:277
void set(difference_type, AnyTy)
Definition: LargeArray.h:337
LAptr largeMallocFloating(size_t bytes)
Definition: NumaMem.cpp:180
pointer iterator
Definition: LargeArray.h:326
const_pointer const_iterator
Definition: LargeArray.h:68
std::enable_if_t< std::is_scalar< U >::value > destroyAt(size_type)
Definition: LargeArray.h:289
iterator end()
Definition: LargeArray.h:341
pointer data()
Definition: LargeArray.h:293
T value_type
Definition: LargeArray.h:60
value_type * pointer
Definition: LargeArray.h:65
iterator begin()
Definition: LargeArray.h:339
const_reference operator[](size_type) const
Definition: LargeArray.h:335
T raw_value_type
Definition: LargeArray.h:59
const_iterator end() const
Definition: LargeArray.h:342
void create(size_type n, Args &&...args)
Allocate and construct.
Definition: LargeArray.h:266
void gDebug(Args &&...GALOIS_USED_ONLY_IN_DEBUG(args))
Prints a debug string from a sequence of things; prints nothing if NDEBUG is defined.
Definition: gIO.h:72
ptrdiff_t difference_type
Definition: LargeArray.h:62
void allocateInterleaved(size_type)
Definition: LargeArray.h:344
static const size_t value
Definition: LargeArray.h:73
Definition: LargeArray.h:72
value_type reference
Definition: LargeArray.h:322
void allocateLocal(size_type n)
Allocates using Thread Local memory policy.
Definition: LargeArray.h:220
const_reference at(difference_type x) const
Definition: LargeArray.h:193
~LargeArray()
Definition: LargeArray.h:182
void deallocate()
Definition: LargeArray.h:358
void construct(Args &&...)
Definition: LargeArray.h:352
LargeArray(LargeArray &&o)
Definition: LargeArray.h:166
AllocType
Definition: LargeArray.h:77
const_iterator begin() const
Definition: LargeArray.h:340
Definition: LargeArray.h:77
const_reference at(difference_type) const
Definition: LargeArray.h:333
void allocateSpecified(size_type, RangeArrayTy)
Definition: LargeArray.h:349
const_iterator end() const
Definition: LargeArray.h:202
void allocateInterleaved(size_type n)
[allocatefunctions] Allocates interleaved across NUMA (memory) nodes.
Definition: LargeArray.h:206
reference at(difference_type)
Definition: LargeArray.h:334
LargeArray & operator=(LargeArray &&o)
Definition: LargeArray.h:172
value_type & reference
Definition: LargeArray.h:63
value_type * const_pointer
Definition: LargeArray.h:325
pointer iterator
Definition: LargeArray.h:67
LAptr largeMallocLocal(size_t bytes)
Definition: NumaMem.cpp:172
unsigned int activeThreads
Definition: Threads.cpp:26
void allocateFloating(size_type)
Definition: LargeArray.h:347
Definition: LargeArray.h:77
value_type const_reference
Definition: LargeArray.h:323
void create(size_type, Args &&...)
Definition: LargeArray.h:356
LAptr largeMallocSpecified(size_t bytes, uint32_t numThreads, RangeArrayTy &threadRanges, size_t elementSize)
Allocates pages for some specified number of bytes, then does NUMA page faulting based on a specified...
Definition: NumaMem.cpp:213
Large array of objects with proper specialization for void type and supporting various allocation and...
Definition: LargeArray.h:53
friend void swap(LargeArray &, LargeArray &)
Definition: LargeArray.h:316
LargeArray()
Definition: LargeArray.h:164
reference at(difference_type x)
Definition: LargeArray.h:194
reference operator[](size_type x)
Definition: LargeArray.h:196
LAptr largeMallocInterleaved(size_t bytes, unsigned numThreads)
Definition: NumaMem.cpp:150
pointer data()
Definition: LargeArray.h:363
LargeArray(void *, size_t)
Definition: LargeArray.h:311
std::enable_if_t<!std::is_scalar< U >::value > destroyAt(size_type n)
Definition: LargeArray.h:284
std::enable_if_t<!std::is_scalar< internal::Val_ty< I > >::value > destroy(I first, I last)
Definition: ParallelSTL.h:300
const value_type & const_reference
Definition: LargeArray.h:64
void allocateLocal(size_type, bool=true)
Definition: LargeArray.h:346
void constructAt(size_type n, Args &&...args)
Definition: LargeArray.h:260
size_type size() const
Definition: LargeArray.h:198
std::unique_ptr< void, internal::largeFreer > LAptr
Definition: NumaMem.h:39
const_pointer data() const
Definition: LargeArray.h:292
void allocateBlocked(size_type n)
Allocates using blocked memory policy.
Definition: LargeArray.h:213
iterator end()
Definition: LargeArray.h:201
size_t size_type
Definition: LargeArray.h:61
static const bool has_value
Definition: LargeArray.h:69
const_iterator begin() const
Definition: LargeArray.h:200
const_reference operator[](size_type x) const
Definition: LargeArray.h:195
ptrdiff_t difference_type
Definition: LargeArray.h:321
const_pointer data() const
Definition: LargeArray.h:362
void allocate(size_type n, AllocType t)
Definition: LargeArray.h:78
const_pointer const_iterator
Definition: LargeArray.h:327
void * value_type
Definition: LargeArray.h:319
void allocateFloating(size_type n)
Allocates using no memory policy (no pre alloc)
Definition: LargeArray.h:227
void deallocate()
Definition: LargeArray.h:271
void construct(Args &&...args)
[allocatefunctions]
Definition: LargeArray.h:254
Definition: LargeArray.h:77
Definition: LargeArray.h:77
const value_type * const_pointer
Definition: LargeArray.h:66
void allocateSpecified(size_type numberOfElements, RangeArrayTy &threadRanges)
Allocate memory to threads based on a provided array specifying which threads receive which elements ...
Definition: LargeArray.h:240
value_type * pointer
Definition: LargeArray.h:324
iterator begin()
Definition: LargeArray.h:199
void allocateBlocked(size_type)
Definition: LargeArray.h:345
size_t size_type
Definition: LargeArray.h:320
void constructAt(size_type, Args &&...)
Definition: LargeArray.h:354