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 | |
---|
35 | BZ_NAMESPACE(blitz) |
---|
36 | |
---|
37 | template<typename P_type> |
---|
38 | void 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 */ |
---|
87 | template<typename P_type> |
---|
88 | inline 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 | |
---|
147 | BZ_NAMESPACE_END |
---|
148 | |
---|
149 | #endif // BZ_MEMBLOCK_CC |
---|