source: XIOS/dev/dev_olga/src/extern/blitz/include/blitz/memblock.cc @ 1022

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 4.9 KB
Line 
1/***************************************************************************
2 * blitz/memblock.cc      MemoryBlock<T> and MemoryBlockReference<T> methods
3 *
4 * $Id$
5 *
6 * Copyright (C) 1997-2011 Todd Veldhuizen <tveldhui@acm.org>
7 *
8 * This file is a part of Blitz.
9 *
10 * Blitz is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation, either version 3
13 * of the License, or (at your option) any later version.
14 *
15 * Blitz is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with Blitz.  If not, see <http://www.gnu.org/licenses/>.
22 *
23 * Suggestions:          blitz-devel@lists.sourceforge.net
24 * Bugs:                 blitz-support@lists.sourceforge.net   
25 *
26 * For more information, please see the Blitz++ Home Page:
27 *    https://sourceforge.net/projects/blitz/
28 *
29 ***************************************************************************/
30#ifndef BZ_MEMBLOCK_CC
31#define BZ_MEMBLOCK_CC
32
33#include <blitz/numtrait.h>
34
35BZ_NAMESPACE(blitz)
36
37template<typename P_type>
38void MemoryBlock<P_type>::deallocate()
39{ 
40  const sizeType byteWidth= simdTypes<P_type>::byteWidth;
41  const int cacheLineSize = BZ_L1_CACHE_LINE_SIZE;   
42 
43#ifdef BZ_ALIGN_BLOCKS_ON_CACHELINE_BOUNDARY
44  const sizeType minLengthToAlign = 
45    BZ_CACHE_LINES_TO_ALIGN*cacheLineSize;
46#else
47  const sizeType minLengthToAlign = blitz::huge(size_t());
48#endif
49 
50  const sizeType numBytes = length_ * sizeof(T_type);
51 
52  // depending on the situation, the block was allocated as any of
53  // three different types, so we need to take care to get it right
54  // when freeing
55
56  if (!allocatedByUs_)
57    // the block was allocated by someone else, so it should just be freed
58    delete [] dataBlockAddress_;
59
60  else {
61    // we allocated the block, so it may have been shifted
62    if ((numBytes < minLengthToAlign) || (cacheLineSize%byteWidth !=0)) {
63      // block was not cache line shifted
64      delete [] dBA_tv_;
65    }
66    else {
67      // block was cache line shifted, manually call destructors
68      if (!NumericTypeTraits<T_type>::hasTrivialCtor)
69        for (sizeType i=0; i < length_; ++i)
70          data_[i].~T_type();
71      delete [] dBA_char_;
72    }
73  }
74}
75
76
77/** Allocate a memory block. If we're allocating a large array it may
78    be desireable for performance reasons to force the array to start
79    on a cache line boundary.  We do this by allocating a little more
80    memory than necessary, then shifting the pointer to the next cache
81    line boundary. Note that this only works if the SIMD byte width of
82    P_type fits evenly into the cache line size, otherwise we may have
83    to allocate a lot more memory to be sure to get to a common
84    multiple of both the cache line size and the size of the
85    object. This can easily be the case for multicomponent containers,
86    and in this case, nothing is done.x  */ 
87template<typename P_type>
88inline void MemoryBlock<P_type>::allocate(sizeType length)
89{
90    TAU_TYPE_STRING(p1, "MemoryBlock<T>::allocate() [T="
91        + CT(P_type) + "]");
92    TAU_PROFILE(p1, "void ()", TAU_BLITZ);
93
94    const sizeType vecWidth= simdTypes<P_type>::vecWidth;
95    const sizeType byteWidth= simdTypes<P_type>::byteWidth;
96    const int cacheLineSize = BZ_L1_CACHE_LINE_SIZE;   
97
98    BZASSERT(length%vecWidth==0);
99
100#ifdef BZ_ALIGN_BLOCKS_ON_CACHELINE_BOUNDARY
101    const sizeType minLengthToAlign = 
102      BZ_CACHE_LINES_TO_ALIGN*cacheLineSize;
103#else
104    const sizeType minLengthToAlign = blitz::huge(size_t());
105#endif
106
107    const sizeType numBytes = length * sizeof(T_type);
108
109    //cout << "Size: " << sizeof(P_type) << ", alignment " << __alignof__(P_type) << endl;
110
111    if ((numBytes < minLengthToAlign) || (cacheLineSize%byteWidth !=0)) {
112      // no shifting to cache line
113      dBA_tv_ = 
114        new typename simdTypes<P_type>::vecType[length/vecWidth];
115      data_= dataBlockAddress_;
116    }
117    else {
118      // shift to cache line
119
120      dBA_char_ = new char[numBytes + cacheLineSize + 1];
121
122      // Shift to the next cache line boundary.
123      diffType offsetToCacheLine = 
124        diffType(dBA_char_) % cacheLineSize;
125      diffType shift = (offsetToCacheLine == 0) ? 0 :
126        (cacheLineSize - offsetToCacheLine);
127      data_char_ = dBA_char_ + shift;
128     
129      // Use placement new to construct types with nontrival ctors
130      if (!NumericTypeTraits<T_type>::hasTrivialCtor) {
131        for (sizeType i=0; i < length; ++i)
132          new(&data_[i]) T_type;
133      }
134    }
135
136    allocatedByUs_ = true;
137
138#ifdef BZ_DEBUG_LOG_ALLOCATIONS
139    cout << "MemoryBlock: allocated " << setw(8) << length
140         << " at " << ((void *)dataBlockAddress_) << endl;
141#endif
142
143    BZASSERT(isVectorAligned(data_));
144}
145
146
147BZ_NAMESPACE_END
148
149#endif // BZ_MEMBLOCK_CC
Note: See TracBrowser for help on using the repository browser.