vSMC
vSMC: Scalable Monte Carlo
aligned_memory.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/utility/aligned_memory.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013,2014, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_UTILITY_ALIGNED_MEMORY
33 #define VSMC_UTILITY_ALIGNED_MEMORY
34 
35 #include <vsmc/internal/common.hpp>
36 
37 #if VSMC_HAS_POSIX
38 #include <stdlib.h>
39 #elif defined(VSMC_MSVC)
40 #include <malloc.h>
41 #endif
42 
43 #if VSMC_HAS_TBB_MALLOC
44 #include <tbb/scalable_allocator.h>
45 #endif
46 
47 #if VSMC_HAS_MKL
48 #include <mkl_service.h>
49 #endif
50 
53 #ifndef VSMC_ALIGNED_MEMORY_TYPE
54 #if VSMC_HAS_POSIX || defined(VSMC_MSVC)
55 #define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySYS
56 #elif VSMC_HAS_TBB_MALLOC
57 #define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryTBB
58 #elif VSMC_HAS_MKL
59 #define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemoryMKL
60 #else
61 #define VSMC_ALIGNED_MEMORY_TYPE ::vsmc::AlignedMemorySTD
62 #endif
63 #endif
64 
65 #define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment) \
66  VSMC_STATIC_ASSERT((Alignment != 0 && (Alignment & (Alignment - 1)) == 0),\
67  USE_AlignedAllocator_WITH_ALIGNEMNT_NOT_A_POWER_OF_TWO)
68 
69 #define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignemnt) \
70  VSMC_STATIC_ASSERT((Alignment >= sizeof(void *)), \
71  USE_AlignedAllocator_WITH_ALIGNMENT_LESS_THAN_SIZEOF_VOID_POINTER)
72 
73 #define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY \
74  VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(Alignment); \
75  VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(Alignment);
76 
77 #define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment) \
78  VSMC_RUNTIME_ASSERT((alignment != 0 && (alignment & (alignment - 1)) == 0),\
79  "**aligned_malloc** USED WITH ALIGNMENT NOT A POWER OF TWO")
80 
81 #define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignemnt) \
82  VSMC_RUNTIME_ASSERT((alignment >= sizeof(void *)), \
83  "**aligned_malloc** USED WITH ALIGNMENT LESS THAN sizeof(void *)")
84 
85 #define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY \
86  VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_POWER_OF_TWO(alignment); \
87  VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY_SIZEOF_VOID(alignment);
88 
89 namespace vsmc {
90 
98 {
99  public :
100 
101  static void *aligned_malloc (std::size_t n, std::size_t alignment)
102  {
104 
105  if (n == 0)
106  return VSMC_NULLPTR;
107 
108  void *orig_ptr = std::malloc(n + alignment + sizeof(void *));
109  if (orig_ptr == VSMC_NULLPTR)
110  throw std::bad_alloc();
111 
112  uintptr_t address = reinterpret_cast<uintptr_t>(orig_ptr);
113  uintptr_t offset = alignment - (address + sizeof(void *)) % alignment;
114  void *ptr = reinterpret_cast<void *>(address + offset + sizeof(void *));
115  void **orig = reinterpret_cast<void **>(address + offset);
116  *orig = orig_ptr;
117 
118  return ptr;
119  }
120 
121  static void aligned_free (void *ptr)
122  {
123  std::free(*reinterpret_cast<void **>(
124  reinterpret_cast<uintptr_t>(ptr) - sizeof(void *)));
125  }
126 }; // class AlignedMemmorySTD
127 
128 #if VSMC_HAS_POSIX
129 
137 {
138  public :
139 
140  static void *aligned_malloc (std::size_t n, std::size_t alignment)
141  {
143 
144  if (n == 0)
145  return VSMC_NULLPTR;
146 
147  void *ptr;
148  if (posix_memalign(&ptr, alignment, n) != 0)
149  throw std::bad_alloc();
150 
151  return ptr;
152  }
153 
154  static void aligned_free (void *ptr) {free(ptr);}
155 }; // class AlignedMallocSYS
156 
157 #elif defined(VSMC_MSVC)
158 
159 class AlignedMemorySYS
160 {
161  public :
162 
163  static void *aligned_malloc (std::size_t n, std::size_t alignment)
164  {
166 
167  if (n == 0)
168  return VSMC_NULLPTR;
169 
170  void *ptr = _aligned_malloc(n, alignment);
171  if (ptr == VSMC_NULLPTR)
172  throw std::bad_alloc();
173 
174  return ptr;
175  }
176 
177  static void aligned_free (void *ptr) {_aligned_free(ptr);}
178 }; // class AlignedMemorySYS
179 
180 #endif // VSMC_HAS_POSIX
181 
182 #if VSMC_HAS_TBB_MALLOC
183 
188 {
189  public :
190 
191  static void *aligned_malloc (std::size_t n, std::size_t alignment)
192  {
194 
195  if (n == 0)
196  return VSMC_NULLPTR;
197 
198  void *ptr = scalable_aligned_malloc(n, alignment);
199  if (ptr == VSMC_NULLPTR)
200  throw std::bad_alloc();
201 
202  return ptr;
203  }
204 
205  static void aligned_free (void *ptr) {scalable_aligned_free(ptr);}
206 }; // class AlignedMemoryTBB
207 
208 #endif // VSMC_HAS_TBB_MALLOC
209 
210 #if VSMC_HAS_MKL
211 
215 {
216  public :
217 
218  static void *aligned_malloc (std::size_t n, std::size_t alignment)
219  {
221 
222  if (n == 0)
223  return VSMC_NULLPTR;
224 
225  void *ptr = mkl_malloc(n, static_cast<int>(alignment));
226  if (ptr == VSMC_NULLPTR)
227  throw std::bad_alloc();
228 
229  return ptr;
230  }
231 
232  static void aligned_free (void *ptr) {mkl_free(ptr);}
233 }; // class AlignedMemoryMKL
234 
235 #endif // VSMC_HAS_MKL
236 
240 
252 template <typename T, std::size_t Alignment = 32,
253  typename Memory = AlignedMemory>
254 class AlignedAllocator : public std::allocator<T>
255 {
256  public :
257 
258  typedef typename std::allocator<T>::size_type size_type;
259  typedef typename std::allocator<T>::pointer pointer;
260 
261  template <typename U> struct rebind
263 
265 
267  std::allocator<T>(other)
269 
270  template <typename U>
272  std::allocator<T>(static_cast<std::allocator<U> >(other))
274 
276 
277  pointer allocate (size_type n, const void * = VSMC_NULLPTR)
278  {
279  return static_cast<pointer>(
280  memory_.aligned_malloc(sizeof(T) * n, Alignment));
281  }
282 
283  void deallocate (pointer ptr, size_type)
284  {
285  if (ptr != VSMC_NULLPTR)
286  memory_.aligned_free(ptr);
287  }
288 
289  private :
290 
291  Memory memory_;
292 }; // class AlignedAllocator
293 
294 } // namespace vsmc
295 
296 #endif // VSMC_UTILITY_ALIGNED_MEMORY
Definition: adapter.hpp:37
AlignedAllocator(const AlignedAllocator< T, Alignment > &other)
static void * aligned_malloc(std::size_t n, std::size_t alignment)
AlignedAllocator< U, Alignment > other
Aligned memory using std::malloc and std::free
Aligned memory using Intel TBB scalable_aligned_malloc and scalable_aligned_free. ...
static void aligned_free(void *ptr)
STL namespace.
#define VSMC_STATIC_ASSERT_UTILITY_ALIGNED_MEMORY
Aligned memory using Intel MKL mkl_malloc and mkl_free
#define VSMC_RUNTIME_ASSERT_UTILITY_ALIGNED_MEMORY
AlignedAllocator(const AlignedAllocator< U, Alignment > &other)
static void * aligned_malloc(std::size_t n, std::size_t alignment)
static void aligned_free(void *ptr)
static void * aligned_malloc(std::size_t n, std::size_t alignment)
::vsmc::AlignedMemorySYS AlignedMemory
Default AlignedMemory type.
static void aligned_free(void *ptr)
Aligned memory using native system aligned memory allocation.
Aligned allocator.
std::allocator< T >::pointer pointer
#define VSMC_NULLPTR
nullptr
Definition: defines.hpp:79
static void * aligned_malloc(std::size_t n, std::size_t alignment)
pointer allocate(size_type n, const void *=nullptr)
static void aligned_free(void *ptr)
void deallocate(pointer ptr, size_type)
#define VSMC_ALIGNED_MEMORY_TYPE
Default AlignedMemory type.
std::allocator< T >::size_type size_type