pmm  1.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
pmm_util.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008-2010 Robert Higgins
3  Author: Robert Higgins <robert.higgins@ucd.ie>
4 
5  This file is part of PMM.
6 
7  PMM is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  PMM is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with PMM. If not, see <http://www.gnu.org/licenses/>.
19 */
20 /*!
21  * @file pmm_util.c
22  * @brief Utility functions for benchmark executables
23  *
24  * Code that implements utility functions for benchmark authors
25  */
26 #if HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include <stdio.h>
31 #include <sys/time.h>
32 #include <sys/resource.h>
33 #include <libxml/encoding.h>
34 #include <libxml/xmlwriter.h>
35 //#include <libxml/xmlmemory.h>
36 //#include <libxml/parser.h>
37 //
38 #ifdef HAVE_PAPI
39 #include <papi.h>
40 #endif
41 
42 #include "pmm_util.h"
43 
44 /* TODO Windows DDL libraries share data and so this library will need to be
45  * modified so that these timeval structures are declared in the executing
46  * program and not the library
47  *
48  * TODO return error codes from timer calls
49  *
50  * TODO determine whether it is necessary to get rusage stats on child processes
51  * as well as self
52  *
53  */
54 
55 void print_xml_results(struct timeval *walltime, struct timeval *usedtime);
56 int print_xml_time_element(xmlTextWriterPtr writer, const char *name,
57  struct timeval *time);
58 void print_plain_results(struct timeval *walltime, struct timeval *usedtime);
59 
60 // PAPI variables
61 #ifdef HAVE_PAPI
62 float papi_realtime;
63 float papi_usedtime;
64 long_long papi_complexity;
65 float papi_mflops;
66 #else
67 // real time variables (wall clock)
68 struct timeval realtime_start;
69 struct timeval realtime_end;
70 struct timeval realtime_total;
71 struct timeval usedtime_total;
72 #endif
73 
74 // used time variables (from rusage)
75 struct rusage usage_start;
76 struct rusage usage_end;
77 struct rusage usage_temp;
78 
79 long long pmm_complexity;
80 
81 #define XMLENCODING "ISO-8859-1"
82 
83 void pmm_timer_init(long long complexity)
84 {
85  pmm_complexity = complexity;
86  return;
87 }
88 
90 
91  return;
92 }
93 
95 #ifdef HAVE_PAPI
96  int ret;
97 #endif
98 
99  getrusage(RUSAGE_SELF, &usage_start);
100 
101 #ifdef HAVE_PAPI
102  ret = PAPI_flops(&papi_realtime, &papi_usedtime, &papi_complexity,
103  &papi_mflops);
104 
105  if(ret != PAPI_OK) {
106  printf("Could not initialize PAPI_flops\n");
107  printf("Your platform may not support the floating point operation.\n");
108  exit(PMM_EXIT_GENFAIL);
109  }
110 #else
111  gettimeofday(&realtime_start, NULL);
112 #endif
113 
114  return;
115 }
116 
118 
119 #ifdef HAVE_PAPI
120  int ret;
121 
122  ret = PAPI_flops(&papi_realtime, &papi_usedtime, &papi_complexity,
123  &papi_mflops);
124 
125  if(ret != PAPI_OK) {
126  printf("Could not finalize PAPI_flops\n");
127  printf("Your platform may not support the floating point operation.\n");
128  exit(PMM_EXIT_GENFAIL);
129  }
130 #else
131  gettimeofday(&realtime_end, NULL);
132 #endif
133 
134  getrusage(RUSAGE_SELF, &usage_end);
135 
136  return;
137 }
138 
140 
141 
142 #ifdef HAVE_PAPI
143  printf("%d %d\n", (int)papi_realtime, (int)(1000000.0*(papi_realtime-
144  (int)papi_realtime)));
145  printf("%d %d\n", (int)papi_usedtime, (int)(1000000.0*(papi_usedtime-
146  (int)papi_usedtime)));
147  printf("%lld\n", papi_complexity);
148 #else
150 
151  // use usage_temp to store the total system and user timevals
152  timersub(&usage_end.ru_utime, &usage_start.ru_utime, &usage_temp.ru_utime);
153  timersub(&usage_end.ru_stime, &usage_start.ru_stime, &usage_temp.ru_stime);
154 
155  //add the total system and user timevals to usedtime
156  //TODO rusage time not useful if routine is multithread and host is SMP
157  timeradd(&usage_temp.ru_utime, &usage_temp.ru_stime, &usedtime_total);
158 
159 
160 
161  //TODO implment return of data via xml
162  //print_xml_results(&realtime_total, &usedtime_total);
164 #endif
165 
166 
167  return;
168 }
169 
170 /*
171  * TODO pass up return conditions instead of terminating
172  */
173 void print_xml_results(struct timeval *walltime, struct timeval *usedtime) {
174 
175  int rc;
176  xmlTextWriterPtr writer;
177  xmlBufferPtr buf;
178 
179  buf = xmlBufferCreate();
180  if(buf == NULL) {
181  printf("pmm_timer_result: Error creating xml buffer\n");
182  exit(-1);
183  }
184 
185  writer = xmlNewTextWriterMemory(buf, 0);
186  if(writer == NULL) {
187  printf("pmm_timer_result: Error creating xml writer\n");
188  exit(-1);
189  }
190 
191  rc = xmlTextWriterSetIndent(writer, 1);
192  if(rc < 0) {
193  printf("pmm_timer_result: Error setting indent\n");
194  exit(-1);
195  }
196 
197  rc = xmlTextWriterStartDocument(writer, NULL, XMLENCODING, NULL);
198  if(rc < 0) {
199  printf("pmm_timer_result: Error at xmlTextWriterStartDocument\n");
200  exit(-1);
201  }
202 
203  rc = xmlTextWriterStartElement(writer, BAD_CAST "result");
204  if(rc < 0) {
205  printf("pmm_timer_result: Error creating \'result\' element\n");
206  exit(-1);
207  }
208 
209  rc = print_xml_time_element(writer, "walltime", walltime);
210  if(rc < 0) {
211  printf("print_xml_results: Error printing walltime result\n");
212  exit(rc);
213  }
214 
215  rc = print_xml_time_element(writer, "usedtime", usedtime);
216  if(rc < 0) {
217  printf("print_xml_results: Error printing usedtime result\n");
218  exit(rc);
219  }
220 
221 
222  rc = xmlTextWriterEndDocument(writer);
223  if(rc < 0) {
224  printf("print_xml_results: Error closing xml document\n");
225  exit(rc);
226  }
227 
228  xmlFreeTextWriter(writer);
229 
230  printf("%s", (const char*)buf->content);
231 
232  xmlBufferFree(buf);
233 
234 }
235 
236 int print_xml_time_element(xmlTextWriterPtr writer, const char *name,
237  struct timeval *time) {
238  int rc;
239 
240  rc = xmlTextWriterStartElement(writer, BAD_CAST name);
241  if(rc < 0) {
242  printf("print_xml_time_element: Error opening time element\n");
243  return rc;
244  }
245 
246  rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "seconds", "%ld",
247  (long)time->tv_sec);
248  if(rc < 0) {
249  printf("print_xml_time_element: Error writing seconds element\n");
250  return rc;
251  }
252 
253  rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "useconds", "%ld",
254  (long)time->tv_usec);
255  if(rc < 0) {
256  printf("print_xml_time_element: Error writing useconds\n");
257  return rc;
258  }
259 
260  rc = xmlTextWriterEndElement(writer);
261  if(rc < 0) {
262  printf("print_xml_time_element: Error closing time element\n");
263  return rc;
264  }
265 
266  return rc;
267 
268 }
269 
270 void print_plain_results(struct timeval *walltime, struct timeval *usedtime) {
271  FILE *fp;
272 
273  printf("%ld %ld\n", walltime->tv_sec, walltime->tv_usec);
274  printf("%ld %ld\n", usedtime->tv_sec, usedtime->tv_usec);
275  printf("%lld\n", pmm_complexity);
276 
277  fp = fopen("/tmp/pmm_results", "w");
278  fprintf(fp, "%ld %ld\n", walltime->tv_sec, walltime->tv_usec);
279  fprintf(fp, "%ld %ld\n", usedtime->tv_sec, usedtime->tv_usec);
280  fclose(fp);
281 }
282 
283