1 |
|
2 |
/******************************************************* |
3 |
* |
4 |
* Copyright (c) 2003-2008 by University of Queensland |
5 |
* Earth Systems Science Computational Center (ESSCC) |
6 |
* http://www.uq.edu.au/esscc |
7 |
* |
8 |
* Primary Business: Queensland, Australia |
9 |
* Licensed under the Open Software License version 3.0 |
10 |
* http://www.opensource.org/licenses/osl-3.0.php |
11 |
* |
12 |
*******************************************************/ |
13 |
|
14 |
|
15 |
#include <stdio.h> |
16 |
#include <string.h> |
17 |
#include <stdlib.h> |
18 |
#include <time.h> |
19 |
#include <search.h> |
20 |
#ifdef _OPENMP |
21 |
#include <omp.h> |
22 |
#endif |
23 |
|
24 |
#include "blocktimer.h" |
25 |
#include "stdlib.h" |
26 |
#include "string.h" |
27 |
|
28 |
#ifdef PASO_MPI |
29 |
#include "mpi.h" |
30 |
#endif |
31 |
|
32 |
#ifdef BLOCKTIMER |
33 |
static char *g_names[NUM_TIMERS]; /* Names of the timers */ |
34 |
static int g_count[NUM_TIMERS]; /* How many times was the timer incremented? */ |
35 |
static double g_times[NUM_TIMERS]; /* The total time spent in the block */ |
36 |
static double g_start_time; /* Start time for the entire program */ |
37 |
static int g_initialized = 0; /* Has the blocktimer been initialized? */ |
38 |
static int g_end_computed = 0; /* Has the end time been set? */ |
39 |
#endif /* BLOCKTIMER */ |
40 |
|
41 |
void |
42 |
blocktimer_initialize() |
43 |
{ |
44 |
#ifdef BLOCKTIMER |
45 |
int i; |
46 |
|
47 |
for (i=0; i<NUM_TIMERS; i++) { |
48 |
g_names[i] = (char *)NULL; |
49 |
g_times[i] = 0.0; |
50 |
g_count[i] = 0; |
51 |
} |
52 |
|
53 |
if (hcreate(NUM_TIMERS) == 0) { |
54 |
perror("hcreate"); |
55 |
fprintf(stderr, "blocktimer_initialize: Could not initialize hash table\n"); |
56 |
exit(1); |
57 |
} |
58 |
|
59 |
g_initialized = 1; |
60 |
|
61 |
g_start_time = blocktimer_time(); |
62 |
|
63 |
/* Initialize timer for "entire program" to zero so it appears first in the report */ |
64 |
blocktimer_increment("entire program", g_start_time); |
65 |
g_count[0] = 0; /* Reset counter for "entire program" to zero */ |
66 |
#endif /* BLOCKTIMER */ |
67 |
} |
68 |
|
69 |
void |
70 |
blocktimer_increment(__const char *name, double start_time) |
71 |
{ |
72 |
#ifdef BLOCKTIMER |
73 |
int id; |
74 |
|
75 |
if (!g_initialized) { return; } |
76 |
|
77 |
id = blocktimer_getOrCreateTimerId(name); |
78 |
|
79 |
g_times[id] += blocktimer_time() - start_time; |
80 |
g_count[id] += 1; |
81 |
#endif /* BLOCKTIMER */ |
82 |
} |
83 |
|
84 |
int |
85 |
blocktimer_getOrCreateTimerId(__const char *name) |
86 |
{ |
87 |
int id=0; |
88 |
#ifdef BLOCKTIMER |
89 |
char *tmp_str; |
90 |
static int nextId = 0; /* Next timer ID to assign */ |
91 |
ENTRY item, *found_item; |
92 |
|
93 |
if (!g_initialized) { return(0); } |
94 |
|
95 |
/* Has a timer with 'name' already been defined? */ |
96 |
item.key = (char *)name; |
97 |
item.data = (void *) NULL; |
98 |
found_item = hsearch(item, FIND); |
99 |
|
100 |
if (found_item != NULL) { /* Already defined so retrieve it from the hash */ |
101 |
/* Return the ID of the entry we found */ |
102 |
int *idTmp = found_item->data; |
103 |
id = *idTmp; |
104 |
} |
105 |
else { /* Not already defined so create one */ |
106 |
/* malloc new int, can't use stack var or all items share same data */ |
107 |
int *idTmp = (int *)malloc(sizeof(int)); |
108 |
/* Enter the new name in the hash */ |
109 |
if (nextId >= NUM_TIMERS) { |
110 |
fprintf(stderr, "blocktimer: exceeded limit of %d timers, increase NUM_TIMERS\n", NUM_TIMERS); |
111 |
exit(1); |
112 |
} |
113 |
*idTmp = nextId++; |
114 |
item.key = (char *)name; |
115 |
item.data = (void *) idTmp; |
116 |
hsearch(item, ENTER); |
117 |
id = *idTmp; |
118 |
/* Make a copy of the name and save with other names */ |
119 |
tmp_str = malloc(strlen(name)+1); |
120 |
strcpy(tmp_str, name); |
121 |
g_names[id] = tmp_str; |
122 |
} |
123 |
|
124 |
#endif /* BLOCKTIMER */ |
125 |
return(id); |
126 |
} |
127 |
|
128 |
void |
129 |
blocktimer_reportSortByName() |
130 |
{ |
131 |
#ifdef BLOCKTIMER |
132 |
int i; |
133 |
|
134 |
if (!g_initialized) { return; } |
135 |
|
136 |
if (!g_end_computed) { |
137 |
blocktimer_increment("entire program", g_start_time); |
138 |
g_end_computed = 1; |
139 |
} |
140 |
printf("BlockTimer sorted by name (sorting TBD):\n"); |
141 |
for(i=0; i<NUM_TIMERS; i++) { |
142 |
if (g_names[i] != (char *) NULL) { |
143 |
printf(" %7d %15.2f %s\n", g_count[i], g_times[i], g_names[i]); |
144 |
} |
145 |
} |
146 |
#endif /* BLOCKTIMER */ |
147 |
} |
148 |
|
149 |
void |
150 |
blocktimer_reportSortByTime() |
151 |
{ |
152 |
#ifdef BLOCKTIMER |
153 |
int i; |
154 |
|
155 |
if (!g_initialized) { return; } |
156 |
|
157 |
if (!g_end_computed) { |
158 |
blocktimer_increment("entire program", g_start_time); |
159 |
g_end_computed = 1; |
160 |
} |
161 |
printf("BlockTimer sorted by time (sorting TBD):\n"); |
162 |
for(i=0; i<NUM_TIMERS; i++) { |
163 |
if (g_names[i] != (char *) NULL) { |
164 |
printf(" %7d %15.2f seconds for %s\n", g_count[i], g_times[i], g_names[i]); |
165 |
} |
166 |
} |
167 |
#endif /* BLOCKTIMER */ |
168 |
} |
169 |
|
170 |
/* Copied from Paso_timer() */ |
171 |
double |
172 |
blocktimer_time() |
173 |
{ |
174 |
double out=0.0; |
175 |
#ifdef PASO_MPI |
176 |
out = MPI_Wtime(); |
177 |
#else |
178 |
#ifdef _OPENMP |
179 |
out=omp_get_wtime(); |
180 |
#else |
181 |
out=((double) clock())/CLOCKS_PER_SEC; |
182 |
#endif |
183 |
#endif |
184 |
return(out); |
185 |
} |
186 |
|