Lift
Library of parallel computing primitives for GPUs and multi-core CPUs
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
timer.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015, NVIDIA CORPORATION
3  * Copyright (c) 2015, Nuno Subtil <subtil@gmail.com>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the copyright holders nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #pragma once
30 
31 #include "types.h"
32 #include <sys/time.h>
33 
34 #include <stack>
35 
36 namespace lift {
37 
38 template <target_system system>
39 struct timer
40 {
41  struct timeval start_event;
42  bool started;
43  float time_counter;
44 
46  : started(false), time_counter(0.0)
47  { }
48 
49  timer(const timer&) = delete;
50 
51  void start(void)
52  {
53  if (started)
54  {
55  fprintf(stderr, "ERROR: inconsistent timer state\n");
56  abort();
57  }
58 
59  gettimeofday(&start_event, NULL);
60  started = true;
61  }
62 
63  void stop(void)
64  {
65  if (!started)
66  {
67  fprintf(stderr, "ERROR: inconsistent timer state\n");
68  abort();
69  }
70 
71  struct timeval stop_event, res;
72 
73  gettimeofday(&stop_event, NULL);
74 
75  timersub(&stop_event, &start_event, &res);
76  time_counter += res.tv_sec + res.tv_usec / 1000000.0;
77 
78  started = false;
79  }
80 
81  float elapsed_time(void)
82  {
83  return time_counter;
84  }
85 };
86 
87 template <>
88 struct timer<cuda>
89 {
90  typedef struct
91  {
92  cudaEvent_t start;
93  cudaEvent_t end;
94  } sample_type;
95 
96  std::stack<sample_type> retired_events;
97 
98  sample_type active_sample;
99  bool started;
101 
103  : started(false), time_counter(0.0), retired_events()
104  { }
105 
106  timer(const timer&) = delete;
107 
109  {
110  flush();
111  }
112 
113  void start(void)
114  {
115  if (started)
116  {
117  fprintf(stderr, "ERROR: inconsistent timer state\n");
118  abort();
119  }
120 
121  cudaError_t err;
122 
123  err = cudaEventCreate(&active_sample.start);
124  if (err != cudaSuccess)
125  {
126  fprintf(stderr, "ERROR: cudaEventCreate failed (%d): %s\n", err, cudaGetErrorName(err));
127  }
128 
129 
130  err = cudaEventCreate(&active_sample.end);
131  if (err != cudaSuccess)
132  {
133  fprintf(stderr, "ERROR: cudaEventCreate failed (%d): %s\n", err, cudaGetErrorName(err));
134  }
135 
136 
137  err = cudaEventRecord(active_sample.start);
138  if (err != cudaSuccess)
139  {
140  fprintf(stderr, "ERROR: start: cudaEventRecord failed (%d): %s\n", err, cudaGetErrorName(err));
141  }
142 
143 
144  started = true;
145  }
146 
147  void stop(void)
148  {
149  if (!started)
150  {
151  fprintf(stderr, "ERROR: inconsistent timer state\n");
152  abort();
153  }
154 
155  cudaError_t err;
156  err = cudaEventRecord(active_sample.end);
157  if (err != cudaSuccess)
158  {
159  fprintf(stderr, "ERROR: stop: cudaEventRecord failed (%d): %s\n", err, cudaGetErrorName(err));
160  }
161 
162 
163  retired_events.push(active_sample);
164  started = false;
165  }
166 
167 private:
168  void flush(void)
169  {
170  while(!retired_events.empty())
171  {
172  float ms;
173 
174  sample_type sample = retired_events.top();
175  retired_events.pop();
176 
177  cudaEventSynchronize(sample.end);
178  cudaEventElapsedTime(&ms, sample.start, sample.end);
179  time_counter += ms / 1000.0;
180 
181  cudaEventDestroy(sample.start);
182  cudaEventDestroy(sample.end);
183  }
184  }
185 
186 public:
187  float elapsed_time(void)
188  {
189  flush();
190  return time_counter;
191  }
192 };
193 
195 {
197 
199  : elapsed_time(0.0)
200  { }
201 
203  {
204  elapsed_time += other.elapsed_time;
205  return *this;
206  }
207 
208  template <typename Timer>
209  void add(Timer& timer)
210  {
211  elapsed_time += timer.elapsed_time();
212  }
213 };
214 
215 } // namespace lift
timer()
Definition: timer.h:45
bool started
Definition: timer.h:42
time_series & operator+=(const time_series &other)
Definition: timer.h:202
void stop(void)
Definition: timer.h:63
void stop(void)
Definition: timer.h:147
void add(Timer &timer)
Definition: timer.h:209
void start(void)
Definition: timer.h:51
float elapsed_time(void)
Definition: timer.h:81
float time_counter
Definition: timer.h:100
std::stack< sample_type > retired_events
Definition: timer.h:96
struct timeval start_event
Definition: timer.h:41
float elapsed_time(void)
Definition: timer.h:187
sample_type active_sample
Definition: timer.h:98
float elapsed_time
Definition: timer.h:196
void start(void)
Definition: timer.h:113
float time_counter
Definition: timer.h:43