source: src/base/timer.cpp@ 894a5f

Last change on this file since 894a5f was 894a5f, checked in by Julian Iseringhausen <isering@…>, 14 years ago

Parallel performance update.

git-svn-id: https://svn.version.fz-juelich.de/scafacos/trunk@1314 5161e1c8-67bf-11de-9fd5-51895aff932f

  • Property mode set to 100644
File size: 5.2 KB
RevLine 
[dfed1c]1/**
2 * @file timer.cpp
3 * @author Julian Iseringhausen <isering@ins.uni-bonn.de>
4 * @date Tue Sep 6 16:17:40 2011
5 *
6 * @brief Class to measure timings.
7 *
8 */
9
10#ifdef HAVE_CONFIG_H
11#include <config.h>
12#endif
13
14#ifdef HAVE_MPI
15#include <mpi.h>
16#endif
17
18#include <iostream>
19#include <limits>
20#include <sstream>
21
22#include "base/helper.hpp"
23#include "base/timer.hpp"
24#include "comm/comm.hpp"
25#include "thirdparty/pugixml/pugixml.hpp"
26#include "mg.hpp"
27
28using namespace VMG;
29
30std::map<std::string, TimerData> Timer::td;
31
32void Timer::Start(std::string event)
33{
34#ifdef HAVE_MPI
35#ifdef DEBUG_MEASURE_TIME
36 std::map<std::string, TimerData>::iterator iter = td.find(event);
37 if (iter == td.end())
38 iter = td.insert(std::make_pair(event, TimerData())).first;
39
40 iter->second.time_start = MPI_Wtime();
41#endif
42#endif
43}
44
45void Timer::Stop(std::string event)
46{
47#ifdef HAVE_MPI
48#ifdef DEBUG_MEASURE_TIME
49 double time_end = MPI_Wtime();
50
51 std::map<std::string, TimerData>::iterator iter = td.find(event);
52
53 if (time_end - iter->second.time_start < std::numeric_limits<double>::min())
54 ++(iter->second.warning);
55
56 ++(iter->second.total);
57
58 iter->second.duration += time_end - iter->second.time_start;
59#endif
60#endif
61}
62
63void Timer::Clear()
64{
65 td.clear();
66}
67
68pugi::xml_node Timer::ToXMLNode()
69{
70 std::map<std::string, TimerData>::iterator iter;
71
[1610dc]72 pugi::xml_node node_process;
73 node_process.append_attribute("Rank").set_value(MG::GetComm()->GlobalRank());
[dfed1c]74
75 pugi::xml_node node_timings = node_process.append_child("Timings");
76
77 for (iter=Timer::td.begin(); iter!=Timer::td.end(); ++iter) {
78
79 pugi::xml_node node_entry = node_timings.append_child("Sample");
80 node_entry.append_attribute("Name").set_value(Helper::ToString(iter->first).c_str());
81
[1610dc]82 node_entry.append_child("Duration")
83 .append_child(pugi::node_pcdata)
84 .set_value(Helper::ToString(iter->second.duration).c_str());
[dfed1c]85
[1610dc]86 node_entry.append_child("Warnings")
87 .append_child(pugi::node_pcdata)
88 .set_value(Helper::ToString(iter->second.warning).c_str());
[dfed1c]89
[1610dc]90 node_entry.append_child("Total")
91 .append_child(pugi::node_pcdata)
92 .set_value(Helper::ToString(iter->second.total).c_str());
[dfed1c]93
94 }
95
96 return node_process;
97}
98
99std::string Timer::ToString()
100{
101 pugi::xml_node node = Timer::ToXMLNode();
102 std::stringstream str;
103 node.print(str);
104 return str.str();
105}
106
107void Timer::Print()
108{
109#ifdef DEBUG_MEASURE_TIME
110 std::map<std::string, TimerData>::const_iterator iter;
111 Comm& comm = *MG::GetComm();
112
113 if (comm.GlobalRank() == 0) {
114 comm.PrintStringOnce("Running times:");
115 for (iter=Timer::td.begin(); iter!=Timer::td.end(); ++iter)
[894a5f]116 comm.PrintStringOnce(" %s: %e s (%d)", iter->first.c_str(), iter->second.duration, iter->second.total);
[dfed1c]117 }
118#endif
119}
120
[894a5f]121template <class T>
122static T min(T* data, int num_data, int& at_rank)
123{
124 at_rank = 0;
125 T min = data[0];
126
127 for (int i=1; i<num_data; ++i)
128 if (data[i] < min) {
129 at_rank = i;
130 min = data[i];
131 }
132 return min;
133}
134
135template <class T>
136static T max(T* data, int num_data, int& at_rank)
137{
138 at_rank = 0;
139 T max = data[0];
140
141 for (int i=1; i<num_data; ++i)
142 if (data[i] > max) {
143 at_rank = i;
144 max = data[i];
145 }
146 return max;
147}
148
149template <class T>
150static vmg_float avg(T* data, int num_data)
151{
152 vmg_float average = 0.0;
153 vmg_float num_data_inv = 1.0 / static_cast<vmg_float>(num_data);
154 for (int i=0; i<num_data; ++i)
155 average += data[i] * num_data_inv;
156 return average;
157}
158
159void Timer::PrintGlobal()
160{
161#ifdef DEBUG_MEASURE_TIME
162 std::map<std::string, TimerData>::const_iterator iter;
163 Comm& comm = *MG::GetComm();
164 char name[80];
165 int rank, size;
166
167 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
168 MPI_Comm_size(MPI_COMM_WORLD, &size);
169
170 vmg_float times[size];
171 int calls[size];
172
173 comm.PrintStringOnce("Running times (global):");
174
175 for (iter=Timer::td.begin(); iter!=Timer::td.end(); ++iter) {
176 std::strcpy(name, iter->first.c_str());
177 MPI_Bcast(name, 80, MPI_CHAR, 0, MPI_COMM_WORLD);
178 MPI_Gather(&Timer::td[name].duration, 1, MPI_DOUBLE, times, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
179 MPI_Gather(&Timer::td[name].total, 1, MPI_INT, calls, 1, MPI_INT, 0, MPI_COMM_WORLD);
180
181 if (rank == 0) {
182 int min_calls, max_calls, avg_calls;
183 vmg_float min_duration, max_duration, avg_duration;
184 int rank_min_calls, rank_max_calls, rank_min_duration, rank_max_duration;
185
186 min_duration = min(times, size, rank_min_duration);
187 max_duration = max(times, size, rank_max_duration);
188 avg_duration = avg(times, size);
189 min_calls = min(calls, size, rank_min_calls);
190 max_calls = max(calls, size, rank_max_calls);
191 avg_calls = avg(calls, size);
192
193 comm.PrintStringOnce(" %s: %e s (%d)", iter->first.c_str(), iter->second.duration, iter->second.total);
194 comm.PrintStringOnce(" Min: %e s @ %d", min_duration, rank_min_duration);
195 comm.PrintStringOnce(" Max: %e s @ %d", max_duration, rank_max_duration);
196 comm.PrintStringOnce(" Avg: %e s", avg_duration);
197 comm.PrintStringOnce(" Min calls: %d @ %d", min_calls, rank_min_calls);
198 comm.PrintStringOnce(" Max calls: %d @ %d", max_calls, rank_max_calls);
199 comm.PrintStringOnce(" Avg calls: %f", avg_calls);
200 }
201 }
202
203#endif
204}
205
[dfed1c]206std::ostream& VMG::operator<<(std::ostream& out, const Timer&)
207{
208 return out << Timer::ToString();
209}
Note: See TracBrowser for help on using the repository browser.