- Main Page
- Modules
- Namespaces
- Classes
- Files

- Search for |

- File List
- File Members

# samples/common/classes/NvElementProfiler.cpp

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
    00003  *
    00004  * Redistribution and use in source and binary forms, with or without
    00005  * modification, are permitted provided that the following conditions
    00006  * are met:
    00007  *  * Redistributions of source code must retain the above copyright
    00008  *    notice, this list of conditions and the following disclaimer.
    00009  *  * Redistributions in binary form must reproduce the above copyright
    00010  *    notice, this list of conditions and the following disclaimer in the
    00011  *    documentation and/or other materials provided with the distribution.
    00012  *  * Neither the name of NVIDIA CORPORATION nor the names of its
    00013  *    contributors may be used to endorse or promote products derived
    00014  *    from this software without specific prior written permission.
    00015  *
    00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
    00017  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    00018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    00019  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    00020  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    00021  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    00022  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    00023  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    00024  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    00026  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00027  */
    00028
    00029 #include <iostream>
    00030 #include <string.h>
    00031 #include <map>
    00032 #include <stdint.h>
    00033 #include "NvElementProfiler.h"
    00034
    00035 #define LOCK() pthread_mutex_lock(&profiler_lock)
    00036 #define UNLOCK() pthread_mutex_unlock(&profiler_lock)
    00037
    00038 #define RETURN_IF_DISABLED() \
    00039     if (!enabled) { \
    00040         UNLOCK(); \
    00041         return; \
    00042     }
    00043
    00044 #define GET_TIME(timeval) gettimeofday(timeval, NULL);
    00045
    00046 #define TIMESPEC_DIFF_USEC(timespec1, timespec2) \
    00047     (((timespec1)->tv_sec - (timespec2)->tv_sec) * 1000000L + \
    00048         (timespec1)->tv_usec - (timespec2)->tv_usec)
    00049
    00050 using namespace std;
    00051
    00052 NvElementProfiler::NvElementProfiler(ProfilerField fields)
    00053     :valid_fields(fields)
    00054 {
    00055     enabled = false;
    00056     unit_id_counter = 0;
    00057
    00058     reset();
    00059
    00060     pthread_mutex_init(&profiler_lock, NULL);
    00061 }
    00062
    00063 NvElementProfiler::~NvElementProfiler()
    00064 {
    00065     LOCK();
    00066     reset();
    00067     UNLOCK();
    00068     pthread_mutex_destroy(&profiler_lock);
    00069 }
    00070 void
    00071 NvElementProfiler::enableProfiling(bool reset_data)
    00072 {
    00073     LOCK();
    00074     if (enabled)
    00075     {
    00076         UNLOCK();
    00077         return;
    00078     }
    00079
    00080     if(reset_data)
    00081     {
    00082         reset();
    00083     }
    00084
    00085     enabled = true;
    00086     UNLOCK();
    00087 }
    00088
    00089 void
    00090 NvElementProfiler::disableProfiling()
    00091 {
    00092     LOCK();
    00093     RETURN_IF_DISABLED();
    00094
    00095     data_int.accumulated_time.tv_sec +=
    00096         (data_int.stop_time.tv_sec - data_int.start_time.tv_sec);
    00097     data_int.accumulated_time.tv_usec +=
    00098         (data_int.stop_time.tv_usec - data_int.start_time.tv_usec);
    00099     data_int.start_time.tv_sec = 0;
    00100     data_int.start_time.tv_usec = 0;
    00101     data_int.stop_time.tv_sec = 0;
    00102     data_int.stop_time.tv_usec = 0;
    00103     enabled = false;
    00104     UNLOCK();
    00105 }
    00106
    00107 void NvElementProfiler::getProfilerData(NvElementProfiler::NvElementProfilerData &data)
    00108 {
    00109     uint64_t total_time;
    00110
    00111     LOCK();
    00112
    00113     total_time = data_int.accumulated_time.tv_sec * 1000000L +
    00114         data_int.accumulated_time.tv_usec +
    00115         TIMESPEC_DIFF_USEC(&data_int.stop_time, &data_int.start_time);
    00116
    00117     if (data_int.total_processed_units == 0 || total_time == 0)
    00118     {
    00119         data.average_fps = 0;
    00120     }
    00121     else
    00122     {
    00123         data.average_fps = ((float) (data_int.total_processed_units - 1)) *
    00124             1000000 / total_time;
    00125     }
    00126
    00127     if (data_int.total_processed_units == 0)
    00128     {
    00129         data.max_latency_usec = 0;
    00130         data.min_latency_usec = 0;
    00131         data.average_latency_usec = 0;
    00132     }
    00133     else
    00134     {
    00135         data.max_latency_usec = data_int.max_latency_usec;
    00136         data.min_latency_usec = data_int.min_latency_usec;
    00137         data.average_latency_usec =
    00138             data_int.total_latency / data_int.total_processed_units;
    00139     }
    00140
    00141     data.profiling_time.tv_sec =
    00142         data_int.accumulated_time.tv_sec + data_int.stop_time.tv_sec -
    00143                 data_int.start_time.tv_sec;
    00144
    00145     data.profiling_time.tv_usec =
    00146         data_int.accumulated_time.tv_usec + data_int.stop_time.tv_usec -
    00147                 data_int.start_time.tv_usec;
    00148
    00149     if (data.profiling_time.tv_usec < 0)
    00150     {
    00151         data.profiling_time.tv_usec += 1000000;
    00152         data.profiling_time.tv_sec--;
    00153     }
    00154
    00155     if (data.profiling_time.tv_usec > 1000000)
    00156     {
    00157         data.profiling_time.tv_usec -= 1000000;
    00158         data.profiling_time.tv_sec++;
    00159     }
    00160
    00161     data.total_processed_units = data_int.total_processed_units;
    00162     data.num_late_units = data_int.num_late_units;
    00163     data.valid_fields = valid_fields;
    00164     UNLOCK();
    00165 }
    00166
    00167 void NvElementProfiler::printProfilerData(ostream &out_stream)
    00168 {
    00169     NvElementProfilerData data;
    00170     getProfilerData(data);
    00171
    00172     if (data.valid_fields & PROFILER_FIELD_FPS)
    00173     {
    00174         out_stream << "Total Profiling time = " <<
    00175             (data.profiling_time.tv_sec +
    00176                 (data.profiling_time.tv_usec / 1000000.0)) << endl;
    00177         out_stream << "Average FPS = " << data.average_fps << endl;
    00178     }
    00179     if (data.valid_fields & PROFILER_FIELD_TOTAL_UNITS)
    00180     {
    00181         out_stream << "Total units processed = " <<
    00182             data.total_processed_units << endl;
    00183     }
    00184     if (data.valid_fields & PROFILER_FIELD_LATE_UNITS)
    00185     {
    00186         out_stream << "Num. of late units = " <<
    00187             data.num_late_units << endl;
    00188     }
    00189     if (data.valid_fields & PROFILER_FIELD_LATENCIES)
    00190     {
    00191         out_stream << "Average latency(usec) = " <<
    00192             data.average_latency_usec << endl;
    00193         out_stream << "Minimum latency(usec) = " <<
    00194             data.min_latency_usec << endl;
    00195         out_stream << "Maximum latency(usec) = " <<
    00196             data.max_latency_usec << endl;
    00197     }
    00198 }
    00199
    00200 void
    00201 NvElementProfiler::reset()
    00202 {
    00203     memset(&data_int, 0, sizeof(data_int));
    00204     data_int.min_latency_usec = (uint64_t) -1;
    00205
    00206     unit_start_time_queue.clear();
    00207 }
    00208
    00209 uint64_t
    00210 NvElementProfiler::startProcessing()
    00211 {
    00212     struct timeval time;
    00213     uint64_t ret = 0;
    00214     LOCK();
    00215     if (enabled)
    00216     {
    00217         std::map<uint64_t,struct timeval>::iterator it =
    00218             unit_start_time_queue.end();
    00219
    00220         unit_id_counter++;
    00221         GET_TIME(&time);
    00222
    00223         unit_start_time_queue.insert(it,
    00224                 std::pair<uint64_t,struct timeval>(unit_id_counter, time));
    00225
    00226         ret = unit_id_counter;
    00227     }
    00228     UNLOCK();
    00229     return ret;
    00230 }
    00231
    00232 void
    00233 NvElementProfiler::finishProcessing(uint64_t id, bool is_late)
    00234 {
    00235     struct timeval unit_start_time;
    00236     struct timeval stop_time;
    00237     uint64_t latency;
    00238
    00239     LOCK();
    00240     RETURN_IF_DISABLED();
    00241
    00242     if ((valid_fields & PROFILER_FIELD_LATENCIES) &&
    00243             unit_start_time_queue.empty())
    00244     {
    00245         UNLOCK();
    00246         return;
    00247     }
    00248
    00249     GET_TIME(&stop_time);
    00250
    00251     if (valid_fields & PROFILER_FIELD_LATENCIES)
    00252     {
    00253         std::map<uint64_t, struct timeval>::iterator it;
    00254         if (id)
    00255         {
    00256             it = unit_start_time_queue.find(id);
    00257         }
    00258         else
    00259         {
    00260             it = unit_start_time_queue.begin();
    00261         }
    00262
    00263         if (it == unit_start_time_queue.end())
    00264         {
    00265             UNLOCK();
    00266             return;
    00267         }
    00268         unit_start_time = it->second;
    00269         unit_start_time_queue.erase(it);
    00270
    00271         latency = TIMESPEC_DIFF_USEC(&stop_time, &unit_start_time);
    00272         data_int.total_latency += latency;
    00273
    00274         if (latency < data_int.min_latency_usec)
    00275         {
    00276             data_int.min_latency_usec = latency;
    00277         }
    00278         if(latency > data_int.max_latency_usec)
    00279         {
    00280             data_int.max_latency_usec = latency;
    00281         }
    00282     }
    00283
    00284     data_int.stop_time = stop_time;
    00285
    00286     if (!data_int.start_time.tv_sec && !data_int.start_time.tv_usec)
    00287     {
    00288         data_int.start_time = data_int.stop_time;
    00289     }
    00290
    00291     if (is_late)
    00292     {
    00293         data_int.num_late_units++;
    00294     }
    00295     data_int.total_processed_units++;
    00296
    00297     UNLOCK();
    00298 }