1 /*************************************************************************** 2 ocl_timer.h 3 ------------------- 4 W. Michael Brown 5 6 Class for timing OpenCL routines 7 8 __________________________________________________________________________ 9 This file is part of the Geryon Unified Coprocessor Library (UCL) 10 __________________________________________________________________________ 11 12 begin : Jan Fri 22 2010 13 copyright : (C) 2010 by W. Michael Brown 14 email : brownw@ornl.gov 15 ***************************************************************************/ 16 17 /* ----------------------------------------------------------------------- 18 Copyright (2010) Sandia Corporation. Under the terms of Contract 19 DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains 20 certain rights in this software. This software is distributed under 21 the Simplified BSD License. 22 ----------------------------------------------------------------------- */ 23 24 #ifndef OCL_TIMER_H 25 #define OCL_TIMER_H 26 27 #include "ocl_macros.h" 28 #include "ocl_device.h" 29 30 #ifdef CL_VERSION_1_2 31 #define UCL_OCL_MARKER(cq,event) clEnqueueMarkerWithWaitList(cq,0,nullptr,event) 32 #else 33 #define UCL_OCL_MARKER clEnqueueMarker 34 #endif 35 36 namespace ucl_opencl { 37 38 /// Class for timing OpenCL events 39 class UCL_Timer { 40 public: UCL_Timer()41 inline UCL_Timer() : start_event(nullptr), stop_event(nullptr), _total_time(0.0f), 42 _initialized(false), has_measured_time(false) { } UCL_Timer(UCL_Device & dev)43 inline UCL_Timer(UCL_Device &dev) : start_event(nullptr), stop_event(nullptr), _total_time(0.0f), 44 _initialized(false), has_measured_time(false) 45 { init(dev); } 46 ~UCL_Timer()47 inline ~UCL_Timer() { clear(); } 48 49 /// Clear any data associated with timer 50 /** \note init() must be called to reuse timer after a clear() **/ clear()51 inline void clear() { 52 if (_initialized) { 53 CL_DESTRUCT_CALL(clReleaseCommandQueue(_cq)); 54 _initialized=false; 55 _total_time=0.0; 56 } 57 has_measured_time = false; 58 } 59 60 /// Initialize default command queue for timing init(UCL_Device & dev)61 inline void init(UCL_Device &dev) { init(dev,dev.cq()); } 62 63 /// Initialize command queue for timing init(UCL_Device & dev,command_queue & cq)64 inline void init(UCL_Device &dev, command_queue &cq) { 65 clear(); 66 _cq=cq; 67 clRetainCommandQueue(_cq); 68 _initialized=true; 69 has_measured_time = false; 70 } 71 72 /// Start timing on default command queue start()73 inline void start() { 74 UCL_OCL_MARKER(_cq,&start_event); 75 has_measured_time = false; 76 } 77 78 /// Stop timing on default command queue stop()79 inline void stop() { 80 UCL_OCL_MARKER(_cq,&stop_event); 81 has_measured_time = true; 82 } 83 84 /// Block until the start event has been reached on device sync_start()85 inline void sync_start() { 86 CL_SAFE_CALL(clWaitForEvents(1,&start_event)); 87 has_measured_time = false; 88 } 89 90 /// Block until the stop event has been reached on device sync_stop()91 inline void sync_stop() { 92 CL_SAFE_CALL(clWaitForEvents(1,&stop_event)); 93 has_measured_time = true; 94 } 95 96 /// Set the time elapsed to zero (not the total_time) zero()97 inline void zero() { 98 has_measured_time = false; 99 UCL_OCL_MARKER(_cq,&start_event); 100 UCL_OCL_MARKER(_cq,&stop_event); 101 } 102 103 /// Set the total time to zero zero_total()104 inline void zero_total() { _total_time=0.0; } 105 106 /// Add time from previous start and stop to total 107 /** Forces synchronization **/ add_to_total()108 inline double add_to_total() 109 { double t=time(); _total_time+=t; return t/1000.0; } 110 111 /// Add a user specified time to the total (ms) add_time_to_total(const double t)112 inline void add_time_to_total(const double t) { _total_time+=t; } 113 114 /// Return the time (ms) of last start to stop - Forces synchronization time()115 inline double time() { 116 if(!has_measured_time) return 0.0; 117 cl_ulong tstart,tend; 118 CL_SAFE_CALL(clWaitForEvents(1,&stop_event)); 119 CL_SAFE_CALL(clGetEventProfilingInfo(stop_event, 120 CL_PROFILING_COMMAND_START, 121 sizeof(cl_ulong), &tend, nullptr)); 122 CL_SAFE_CALL(clGetEventProfilingInfo(start_event, 123 CL_PROFILING_COMMAND_END, 124 sizeof(cl_ulong), &tstart, nullptr)); 125 clReleaseEvent(start_event); 126 clReleaseEvent(stop_event); 127 has_measured_time = false; 128 return (tend-tstart)*1e-6; 129 } 130 131 /// Return the time (s) of last start to stop - Forces synchronization seconds()132 inline double seconds() { return time()*1e-3; } 133 134 /// Return the total time in ms total_time()135 inline double total_time() { return _total_time; } 136 137 /// Return the total time in seconds total_seconds()138 inline double total_seconds() { return _total_time*1e-3; } 139 140 private: 141 cl_event start_event, stop_event; 142 cl_command_queue _cq; 143 double _total_time; 144 bool _initialized; 145 bool has_measured_time; 146 }; 147 148 } // namespace 149 150 #endif 151