1 |
/* |
2 |
****************************************************************************** |
3 |
* * |
4 |
* COPYRIGHT ACcESS 2004 - All Rights Reserved * |
5 |
* * |
6 |
* This software is the property of ACcESS. No part of this code * |
7 |
* may be copied in any form or by any means without the expressed written * |
8 |
* consent of ACcESS. Copying, use or modification of this software * |
9 |
* by any unauthorised person is illegal unless that person has a software * |
10 |
* license agreement with ACcESS. * |
11 |
* * |
12 |
****************************************************************************** |
13 |
*/ |
14 |
|
15 |
#include "Taipan.h" |
16 |
|
17 |
#include <iostream> |
18 |
#include <cassert> |
19 |
|
20 |
#ifdef _OPENMP |
21 |
#include <omp.h> |
22 |
#endif |
23 |
|
24 |
using namespace std; |
25 |
|
26 |
namespace escript { |
27 |
|
28 |
Taipan::Taipan() : |
29 |
memTable_Root(0), |
30 |
totalElements(0) |
31 |
{ |
32 |
// create and initialise a new StatTable |
33 |
statTable = new Taipan_StatTable; |
34 |
clear_stats(); |
35 |
} |
36 |
|
37 |
Taipan::~Taipan() { |
38 |
|
39 |
long len=0; |
40 |
Taipan_MemTable *tab; |
41 |
Taipan_MemTable *tab_next; |
42 |
|
43 |
// dump memory usage statistics |
44 |
dump_stats(); |
45 |
|
46 |
// deallocate StatTable object |
47 |
delete statTable; |
48 |
|
49 |
// deallocate all managed arrays and the memTable |
50 |
tab = memTable_Root; |
51 |
while (tab != 0) { |
52 |
tab_next = tab->next; |
53 |
len = tab->dim * tab->N; |
54 |
totalElements -= len; |
55 |
delete[] tab->array; |
56 |
delete tab; |
57 |
tab = tab_next; |
58 |
} |
59 |
|
60 |
assert(totalElements == 0); |
61 |
|
62 |
// clear the MemTable root node |
63 |
memTable_Root = 0; |
64 |
|
65 |
// reset totalElements counter |
66 |
totalElements = -1; |
67 |
} |
68 |
|
69 |
double* |
70 |
Taipan::new_array(int dim, int N) { |
71 |
|
72 |
assert(totalElements >= 0); |
73 |
|
74 |
int len = 0; |
75 |
#ifdef _OPENMP |
76 |
int numThreads = omp_get_num_threads(); |
77 |
#else |
78 |
int numThreads = 1; |
79 |
#endif |
80 |
|
81 |
Taipan_MemTable *tab; |
82 |
Taipan_MemTable *new_tab; |
83 |
Taipan_MemTable *tab_prev; |
84 |
|
85 |
// increment count of alloc operations called |
86 |
statTable->requests++; |
87 |
|
88 |
// is a suitable array already available? |
89 |
if (memTable_Root != 0) { |
90 |
tab = memTable_Root; |
91 |
while (tab != 0) { |
92 |
if (tab->dim == dim && |
93 |
tab->N == N && |
94 |
tab->free && |
95 |
tab->numThreads == numThreads) { |
96 |
tab->free = false; |
97 |
return tab->array; |
98 |
} |
99 |
tab_prev = tab; |
100 |
tab = tab->next; |
101 |
} |
102 |
} |
103 |
|
104 |
// otherwise a new array must be allocated |
105 |
|
106 |
// create the corresponding memTable entry |
107 |
len = dim * N; |
108 |
new_tab = new Taipan_MemTable; |
109 |
new_tab->dim = dim; |
110 |
new_tab->N = N; |
111 |
new_tab->numThreads = numThreads; |
112 |
new_tab->free = false; |
113 |
new_tab->next = 0; |
114 |
if (memTable_Root == 0) { |
115 |
memTable_Root = new_tab; |
116 |
} else { |
117 |
tab_prev->next = new_tab; |
118 |
} |
119 |
|
120 |
// allocate and initialise the new array |
121 |
new_tab->array = new double[len]; |
122 |
int i,j; |
123 |
if (N==1) { |
124 |
for (j=0; j<dim; j++) |
125 |
new_tab->array[j]=0.0; |
126 |
} else if (N>1) { |
127 |
#pragma omp parallel for private(i,j) schedule(static) |
128 |
for (i=0; i<N; i++) { |
129 |
for (j=0; j<dim; j++) |
130 |
new_tab->array[j+dim*i]=0.0; |
131 |
} |
132 |
} |
133 |
|
134 |
totalElements += len; |
135 |
|
136 |
// update maximum table size |
137 |
statTable->max_tab_size = (statTable->max_tab_size < totalElements) ? totalElements : statTable->max_tab_size; |
138 |
|
139 |
// increment count of arrays allocated |
140 |
statTable->allocations++; |
141 |
|
142 |
// increment count of elements allocated |
143 |
statTable->allocated_elements += len; |
144 |
|
145 |
return new_tab->array; |
146 |
} |
147 |
|
148 |
void |
149 |
Taipan::delete_array(double* array) { |
150 |
|
151 |
assert(totalElements >= 0); |
152 |
|
153 |
int N; |
154 |
int len = 0; |
155 |
bool found = false; |
156 |
|
157 |
Taipan_MemTable *tab; |
158 |
Taipan_MemTable *tab_next; |
159 |
Taipan_MemTable *tab_prev = 0; |
160 |
|
161 |
// increment count of free operations called |
162 |
statTable->frees++; |
163 |
|
164 |
if (array == 0) { |
165 |
// have been given an empty array, so quit now |
166 |
return; |
167 |
} |
168 |
|
169 |
if (memTable_Root != 0) { |
170 |
|
171 |
// find the table entry for this array and mark it as free |
172 |
tab = memTable_Root; |
173 |
while (tab != 0) { |
174 |
if (tab->array == array) { |
175 |
N = tab->N; |
176 |
tab->free = true; |
177 |
found = true; |
178 |
break; |
179 |
} |
180 |
tab = tab->next; |
181 |
} |
182 |
if (!found) { |
183 |
// this wasn't an array under management, so quit now |
184 |
return; |
185 |
} |
186 |
|
187 |
if (N<=1) { |
188 |
// we never deallocate arrays with N<=1, so quit now |
189 |
return; |
190 |
} |
191 |
|
192 |
// are there any N block arrays still in use? |
193 |
tab = memTable_Root; |
194 |
while (tab != 0) { |
195 |
if (tab->N==N && !tab->free) |
196 |
return; |
197 |
tab = tab->next; |
198 |
} |
199 |
|
200 |
// if not, all N block arrays are deallocated |
201 |
tab = memTable_Root; |
202 |
while (tab != 0) { |
203 |
tab_next = tab->next; |
204 |
if (tab->N == N) { |
205 |
delete[] tab->array; |
206 |
len += tab->dim * N; |
207 |
if (tab_prev != 0) { |
208 |
tab_prev->next = tab->next; |
209 |
} else { |
210 |
memTable_Root = tab->next; |
211 |
} |
212 |
delete tab; |
213 |
// increment count of arrays dealloced |
214 |
statTable->deallocations++; |
215 |
} else { |
216 |
tab_prev = tab; |
217 |
} |
218 |
tab = tab_next; |
219 |
} |
220 |
|
221 |
totalElements -= len; |
222 |
|
223 |
// increment count of elements deallocated |
224 |
statTable->deallocated_elements += len; |
225 |
|
226 |
} else { |
227 |
// what to do if no arrays under management? |
228 |
} |
229 |
} |
230 |
|
231 |
int |
232 |
Taipan::num_arrays() { |
233 |
|
234 |
assert(totalElements >= 0); |
235 |
|
236 |
int num_arrays = 0; |
237 |
|
238 |
Taipan_MemTable *tab; |
239 |
|
240 |
// count all managed arrays in the memTable |
241 |
tab = memTable_Root; |
242 |
while (tab != 0) { |
243 |
num_arrays++; |
244 |
tab = tab->next; |
245 |
} |
246 |
|
247 |
return num_arrays; |
248 |
} |
249 |
|
250 |
int |
251 |
Taipan::num_arrays(int N) { |
252 |
|
253 |
assert(totalElements >= 0); |
254 |
|
255 |
int num_arrays = 0; |
256 |
|
257 |
Taipan_MemTable *tab; |
258 |
|
259 |
// count all managed arrays of N blocks in the memTable |
260 |
tab = memTable_Root; |
261 |
while (tab != 0) { |
262 |
if (tab->N == N) { |
263 |
num_arrays++; |
264 |
} |
265 |
tab = tab->next; |
266 |
} |
267 |
|
268 |
return num_arrays; |
269 |
} |
270 |
|
271 |
int |
272 |
Taipan::num_free(int N) { |
273 |
|
274 |
assert(totalElements >= 0); |
275 |
|
276 |
int num_free = 0; |
277 |
|
278 |
Taipan_MemTable *tab; |
279 |
|
280 |
// count all free managed arrays of N blocks in the memTable |
281 |
tab = memTable_Root; |
282 |
while (tab != 0) { |
283 |
if (tab->N == N) { |
284 |
if (tab->free) { |
285 |
num_free++; |
286 |
} |
287 |
} |
288 |
tab = tab->next; |
289 |
} |
290 |
return num_free; |
291 |
} |
292 |
|
293 |
long |
294 |
Taipan::num_elements() { |
295 |
|
296 |
assert(totalElements >= 0); |
297 |
|
298 |
return totalElements; |
299 |
} |
300 |
|
301 |
void |
302 |
Taipan::dump_stats() { |
303 |
|
304 |
assert(totalElements >= 0); |
305 |
|
306 |
float elMb=statTable->allocated_elements*8.0/1048576; |
307 |
float deelMb=statTable->deallocated_elements*8.0/1048576; |
308 |
float tszMb=statTable->max_tab_size*8.0/1048576; |
309 |
|
310 |
cout << "========== Mem Stats =============================" << endl; |
311 |
cout << "Total Num requests: " << statTable->requests << endl; |
312 |
cout << "Total Num releases: " << statTable->frees << endl; |
313 |
cout << "Total Num allocated arrays: " << statTable->allocations << endl; |
314 |
cout << "Total Num deallocated arrays: " << statTable->deallocations << endl; |
315 |
cout << "Total Num allocated elements: " << statTable->allocated_elements << " (" << elMb << " Mb)" << endl; |
316 |
cout << "Total Num deallocated elements: " << statTable->deallocated_elements << " (" << deelMb << " Mb)" << endl; |
317 |
cout << "Maximum memory buffer size: " << statTable->max_tab_size << " (" << tszMb << " Mb)" << endl; |
318 |
cout << "Curr Num arrays: " << num_arrays() << endl; |
319 |
cout << "Curr Num elements in buffer: " << num_elements() << endl; |
320 |
cout << "==================================================" << endl; |
321 |
} |
322 |
|
323 |
void |
324 |
Taipan::clear_stats() { |
325 |
|
326 |
assert(totalElements >= 0); |
327 |
|
328 |
statTable->requests=0; |
329 |
statTable->frees=0; |
330 |
statTable->allocations=0; |
331 |
statTable->deallocations=0; |
332 |
statTable->allocated_elements=0; |
333 |
statTable->deallocated_elements=0; |
334 |
statTable->max_tab_size=0; |
335 |
} |
336 |
|
337 |
} // end of namespace |