source: src/base/timer.cpp@ 50fc1f3

Last change on this file since 50fc1f3 was a72216, checked in by Olaf Lenz <olenz@…>, 13 years ago

Fixed permissions.

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

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2 * vmg - a versatile multigrid solver
3 * Copyright (C) 2012 Institute for Numerical Simulation, University of Bonn
4 *
5 * vmg is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * vmg is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * @file timer.cpp
21 * @author Julian Iseringhausen <isering@ins.uni-bonn.de>
22 * @date Tue Sep 6 16:17:40 2011
23 *
24 * @brief Class to measure timings.
25 *
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32#ifdef HAVE_MPI
33#include <mpi.h>
34#ifdef HAVE_MARMOT
35#include <enhancempicalls.h>
36#include <sourceinfompicalls.h>
37#endif
38#endif
39
40#include <iostream>
41#include <limits>
42#include <sstream>
43
44#include "base/helper.hpp"
45#include "base/timer.hpp"
46#include "comm/comm.hpp"
47#include "thirdparty/pugixml/pugixml.hpp"
48#include "mg.hpp"
49
50using namespace VMG;
51
52std::map<std::string, TimerData> Timer::td;
53
54void Timer::Start(std::string event)
55{
56#ifdef HAVE_MPI
57#ifdef DEBUG_MEASURE_TIME
58 std::map<std::string, TimerData>::iterator iter = td.find(event);
59 if (iter == td.end())
60 iter = td.insert(std::make_pair(event, TimerData())).first;
61
62 iter->second.time_start = MPI_Wtime();
63#endif
64#endif
65}
66
67void Timer::Stop(std::string event)
68{
69#ifdef HAVE_MPI
70#ifdef DEBUG_MEASURE_TIME
71 double time_end = MPI_Wtime();
72
73 std::map<std::string, TimerData>::iterator iter = td.find(event);
74
75 if (time_end - iter->second.time_start < std::numeric_limits<double>::min())
76 ++(iter->second.warning);
77
78 ++(iter->second.total);
79
80 iter->second.duration += time_end - iter->second.time_start;
81#endif
82#endif
83}
84
85void Timer::Clear()
86{
87 td.clear();
88}
89
90pugi::xml_node Timer::ToXMLNode()
91{
92 std::map<std::string, TimerData>::iterator iter;
93
94 pugi::xml_node node_process;
95 node_process.append_attribute("Rank").set_value(MG::GetComm()->GlobalRank());
96
97 pugi::xml_node node_timings = node_process.append_child("Timings");
98
99 for (iter=Timer::td.begin(); iter!=Timer::td.end(); ++iter) {
100
101 pugi::xml_node node_entry = node_timings.append_child("Sample");
102 node_entry.append_attribute("Name").set_value(Helper::ToString(iter->first).c_str());
103
104 node_entry.append_child("Duration")
105 .append_child(pugi::node_pcdata)
106 .set_value(Helper::ToString(iter->second.duration).c_str());
107
108 node_entry.append_child("Warnings")
109 .append_child(pugi::node_pcdata)
110 .set_value(Helper::ToString(iter->second.warning).c_str());
111
112 node_entry.append_child("Total")
113 .append_child(pugi::node_pcdata)
114 .set_value(Helper::ToString(iter->second.total).c_str());
115
116 }
117
118 return node_process;
119}
120
121std::string Timer::ToString()
122{
123 pugi::xml_node node = Timer::ToXMLNode();
124 std::stringstream str;
125 node.print(str);
126 return str.str();
127}
128
129void Timer::Print()
130{
131#ifdef DEBUG_MEASURE_TIME
132 std::map<std::string, TimerData>::const_iterator iter;
133 Comm& comm = *MG::GetComm();
134
135 if (comm.GlobalRank() == 0) {
136 comm.PrintStringOnce("Running times:");
137 for (iter=Timer::td.begin(); iter!=Timer::td.end(); ++iter)
138 comm.PrintStringOnce(" %s: %e s (%d)", iter->first.c_str(), iter->second.duration, iter->second.total);
139 }
140#endif
141}
142
143template <class T>
144static T min(T* data, int num_data, int& at_rank)
145{
146 at_rank = 0;
147 T min = data[0];
148
149 for (int i=1; i<num_data; ++i)
150 if (data[i] < min) {
151 at_rank = i;
152 min = data[i];
153 }
154 return min;
155}
156
157template <class T>
158static T max(T* data, int num_data, int& at_rank)
159{
160 at_rank = 0;
161 T max = data[0];
162
163 for (int i=1; i<num_data; ++i)
164 if (data[i] > max) {
165 at_rank = i;
166 max = data[i];
167 }
168 return max;
169}
170
171template <class T>
172static vmg_float avg(T* data, int num_data)
173{
174 vmg_float average = 0.0;
175 vmg_float num_data_inv = 1.0 / static_cast<vmg_float>(num_data);
176 for (int i=0; i<num_data; ++i)
177 average += data[i] * num_data_inv;
178 return average;
179}
180
181void Timer::PrintGlobal()
182{
183#ifdef DEBUG_MEASURE_TIME
184 std::map<std::string, TimerData>::const_iterator iter;
185 Comm& comm = *MG::GetComm();
186 char name[80];
187
188 int rank = comm.GlobalRank();
189 int size = comm.GlobalSize();
190
191 vmg_float times[size];
192 int calls[size];
193
194 comm.PrintStringOnce("Running times (global):");
195
196 int timer_size = Timer::td.size();
197 comm.GlobalBroadcast(timer_size);
198
199 if (rank == 0) {
200 for (iter=Timer::td.begin(); iter!=Timer::td.end(); ++iter) {
201 std::strcpy(name, iter->first.c_str());
202 comm.GlobalBroadcast(name);
203 comm.GlobalGather(Timer::td[name].duration, times);
204 comm.GlobalGather(Timer::td[name].total, calls);
205
206 int min_calls, max_calls;
207 vmg_float avg_calls;
208 vmg_float min_duration, max_duration, avg_duration;
209 int rank_min_calls, rank_max_calls, rank_min_duration, rank_max_duration;
210
211 min_duration = min(times, size, rank_min_duration);
212 max_duration = max(times, size, rank_max_duration);
213 avg_duration = avg(times, size);
214 min_calls = min(calls, size, rank_min_calls);
215 max_calls = max(calls, size, rank_max_calls);
216 avg_calls = avg(calls, size);
217
218 comm.PrintStringOnce(" %s: %e s (%d)", iter->first.c_str(), iter->second.duration, iter->second.total);
219 comm.PrintStringOnce(" Min: %e s @ %d", min_duration, rank_min_duration);
220 comm.PrintStringOnce(" Max: %e s @ %d", max_duration, rank_max_duration);
221 comm.PrintStringOnce(" Avg: %e s", avg_duration);
222 comm.PrintStringOnce(" Min calls: %d @ %d", min_calls, rank_min_calls);
223 comm.PrintStringOnce(" Max calls: %d @ %d", max_calls, rank_max_calls);
224 comm.PrintStringOnce(" Avg calls: %f", avg_calls);
225 }
226 }else {
227 for (int i=0; i<timer_size; ++i) {
228 comm.GlobalBroadcast(name);
229 comm.GlobalGather(Timer::td[name].duration, times);
230 comm.GlobalGather(Timer::td[name].total, calls);
231 }
232 }
233
234#endif
235}
236
237std::ostream& VMG::operator<<(std::ostream& out, const Timer&)
238{
239 return out << Timer::ToString();
240}
Note: See TracBrowser for help on using the repository browser.