/[escript]/trunk/esysUtils/src/blocktimer.c
ViewVC logotype

Annotation of /trunk/esysUtils/src/blocktimer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2078 - (hide annotations)
Thu Nov 20 16:10:10 2008 UTC (10 years, 10 months ago) by phornby
File MIME type: text/plain
File size: 4401 byte(s)
Two changes.

1. Move blocktimer from escript to esysUtils.
2. Make it possible to link to paso as a DLL or .so.

Should have no effect on 'nix's

In respect of 1., blocktimer had begun to spring up everywhere, so
for the moment I thought it best to move it to the only other library that
pops up all over the place.

In respect of 2., paso needed to be a DLL in order to use the windows intelc /fast
option, which does aggressive multi-file optimisations. Even in its current form, it either
vectorises or parallelises  hundreds more loops in the esys system than appear in the pragmas.

In achieving 2. I have not been too delicate in adding

PASO_DLL_API

declarations to the .h files in paso/src. Only toward the end of the process of
the conversion, when the number of linker errors dropped below 20, say, did I choosy about what
functions in a header I declared PASO_DLL_API. As a result, there are likely to be many routines
declared as external functions symbols that are in fact internal to the paso DLL. 
Why is this an issue?  It prevents the intelc compiler from getting aggressive on the paso module.
With pain there is sometimes gain. At least all the DLL rules in windows give good
(non-microsoft) compiler writers a chance to really shine.

So, if you should see a PASO_DLL_API on a function in a paso header file,
and think to yourself, "that function is only called in paso, why export it?", then feel free to
delete the PASO_DLL_API export declaration.

Here's hoping for no breakage.....
1 phornby 2078
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    

  ViewVC Help
Powered by ViewVC 1.1.26