Merge pull request #1263 from abidrahmank:pyCLAHE_24
[profile/ivi/opencv.git] / modules / ocl / perf / perf_precomp.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
14 // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other oclMaterials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors as is and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #include "perf_precomp.hpp"
44 #if GTEST_OS_WINDOWS
45 #ifndef NOMINMAX
46 #define NOMINMAX
47 #endif
48 # include <windows.h>
49 #endif
50
51 // This program test most of the functions in ocl module and generate data metrix of x-factor in .csv files
52 // All images needed in this test are in samples/gpu folder.
53 // For haar template, haarcascade_frontalface_alt.xml shouold be in working directory
54 void TestSystem::run()
55 {
56     if (is_list_mode_)
57     {
58         for (vector<Runnable *>::iterator it = tests_.begin(); it != tests_.end(); ++it)
59         {
60             cout << (*it)->name() << endl;
61         }
62
63         return;
64     }
65
66     // Run test initializers
67     for (vector<Runnable *>::iterator it = inits_.begin(); it != inits_.end(); ++it)
68     {
69         if ((*it)->name().find(test_filter_, 0) != string::npos)
70         {
71             (*it)->run();
72         }
73     }
74
75     printHeading();
76     writeHeading();
77
78     // Run tests
79     for (vector<Runnable *>::iterator it = tests_.begin(); it != tests_.end(); ++it)
80     {
81         try
82         {
83             if ((*it)->name().find(test_filter_, 0) != string::npos)
84             {
85                 cout << endl << (*it)->name() << ":\n";
86
87                 setCurrentTest((*it)->name());
88                 //fprintf(record_,"%s\n",(*it)->name().c_str());
89
90                 (*it)->run();
91                 finishCurrentSubtest();
92             }
93         }
94         catch (const Exception &)
95         {
96             // Message is printed via callback
97             resetCurrentSubtest();
98         }
99         catch (const runtime_error &e)
100         {
101             printError(e.what());
102             resetCurrentSubtest();
103         }
104     }
105
106     printSummary();
107     writeSummary();
108 }
109
110
111 void TestSystem::finishCurrentSubtest()
112 {
113     if (cur_subtest_is_empty_)
114         // There is no need to print subtest statistics
115     {
116         return;
117     }
118
119     double cpu_time = cpu_elapsed_ / getTickFrequency() * 1000.0;
120     double gpu_time = gpu_elapsed_ / getTickFrequency() * 1000.0;
121     double gpu_full_time = gpu_full_elapsed_ / getTickFrequency() * 1000.0;
122
123     double speedup = static_cast<double>(cpu_elapsed_) / std::max(1.0, gpu_elapsed_);
124     speedup_total_ += speedup;
125
126     double fullspeedup = static_cast<double>(cpu_elapsed_) / std::max(1.0, gpu_full_elapsed_);
127     speedup_full_total_ += fullspeedup;
128
129     if (speedup > top_)
130     {
131         speedup_faster_count_++;
132     }
133     else if (speedup < bottom_)
134     {
135         speedup_slower_count_++;
136     }
137     else
138     {
139         speedup_equal_count_++;
140     }
141
142     if (fullspeedup > top_)
143     {
144         speedup_full_faster_count_++;
145     }
146     else if (fullspeedup < bottom_)
147     {
148         speedup_full_slower_count_++;
149     }
150     else
151     {
152         speedup_full_equal_count_++;
153     }
154
155     // compute min, max and
156     std::sort(gpu_times_.begin(), gpu_times_.end());
157     double gpu_min = gpu_times_.front() / getTickFrequency() * 1000.0;
158     double gpu_max = gpu_times_.back() / getTickFrequency() * 1000.0;
159     double deviation = 0;
160
161     if (gpu_times_.size() > 1)
162     {
163         double sum = 0;
164
165         for (size_t i = 0; i < gpu_times_.size(); i++)
166         {
167             int64 diff = gpu_times_[i] - static_cast<int64>(gpu_elapsed_);
168             double diff_time = diff * 1000 / getTickFrequency();
169             sum += diff_time * diff_time;
170         }
171
172         deviation = std::sqrt(sum / gpu_times_.size());
173     }
174
175     printMetrics(is_accurate_, cpu_time, gpu_time, gpu_full_time, speedup, fullspeedup);
176     writeMetrics(cpu_time, gpu_time, gpu_full_time, speedup, fullspeedup, gpu_min, gpu_max, deviation);
177
178     num_subtests_called_++;
179     resetCurrentSubtest();
180 }
181
182
183 double TestSystem::meanTime(const vector<int64> &samples)
184 {
185     double sum = accumulate(samples.begin(), samples.end(), 0.);
186     return sum / samples.size();
187 }
188
189
190 void TestSystem::printHeading()
191 {
192     cout << endl;
193     cout<< setiosflags(ios_base::left);
194
195 #if 0
196     cout<<TAB<<setw(7)<< "Accu." << setw(10) << "CPU (ms)" << setw(10) << "GPU, ms"
197         << setw(8) << "Speedup"<< setw(10)<<"GPUTotal" << setw(10) << "Total"
198         << "Description\n";
199     cout<<TAB<<setw(7)<<""<<setw(10)<<""<<setw(10)<<""<<setw(8)<<""<<setw(10)<<"(ms)"<<setw(10)<<"Speedup\n";
200 #endif
201
202     cout<<TAB<< setw(10) << "CPU (ms)" << setw(10) << "GPU, ms"
203         << setw(8) << "Speedup"<< setw(10)<<"GPUTotal" << setw(10) << "Total"
204         << "Description\n";
205     cout<<TAB<<setw(10)<<""<<setw(10)<<""<<setw(8)<<""<<setw(10)<<"(ms)"<<setw(10)<<"Speedup\n";
206
207     cout << resetiosflags(ios_base::left);
208 }
209
210 void TestSystem::writeHeading()
211 {
212     if (!record_)
213     {
214         recordname_ += "_OCL.csv";
215         record_ = fopen(recordname_.c_str(), "w");
216         if(record_ == NULL)
217         {
218             cout<<".csv file open failed.\n";
219             exit(0);
220         }
221     }
222
223     fprintf(record_, "NAME,DESCRIPTION,ACCURACY,DIFFERENCE,CPU (ms),GPU (ms),SPEEDUP,GPUTOTAL (ms),TOTALSPEEDUP,GPU Min (ms),GPU Max (ms), Standard deviation (ms)\n");
224
225     fflush(record_);
226 }
227
228 void TestSystem::printSummary()
229 {
230     cout << setiosflags(ios_base::fixed);
231     cout << "\naverage GPU speedup: x"
232         << setprecision(3) << speedup_total_ / std::max(1, num_subtests_called_)
233         << endl;
234     cout << "\nGPU exceeded: "
235         << setprecision(3) << speedup_faster_count_
236         << "\nGPU passed: "
237         << setprecision(3) << speedup_equal_count_
238         << "\nGPU failed: "
239         << setprecision(3) << speedup_slower_count_
240         << endl;
241     cout << "\nGPU exceeded rate: "
242         << setprecision(3) << (float)speedup_faster_count_ / std::max(1, num_subtests_called_) * 100
243         << "%"
244         << "\nGPU passed rate: "
245         << setprecision(3) << (float)speedup_equal_count_ / std::max(1, num_subtests_called_) * 100
246         << "%"
247         << "\nGPU failed rate: "
248         << setprecision(3) << (float)speedup_slower_count_ / std::max(1, num_subtests_called_) * 100
249         << "%"
250         << endl;
251     cout << "\naverage GPUTOTAL speedup: x"
252         << setprecision(3) << speedup_full_total_ / std::max(1, num_subtests_called_)
253         << endl;
254     cout << "\nGPUTOTAL exceeded: "
255         << setprecision(3) << speedup_full_faster_count_
256         << "\nGPUTOTAL passed: "
257         << setprecision(3) << speedup_full_equal_count_
258         << "\nGPUTOTAL failed: "
259         << setprecision(3) << speedup_full_slower_count_
260         << endl;
261     cout << "\nGPUTOTAL exceeded rate: "
262         << setprecision(3) << (float)speedup_full_faster_count_ / std::max(1, num_subtests_called_) * 100
263         << "%"
264         << "\nGPUTOTAL passed rate: "
265         << setprecision(3) << (float)speedup_full_equal_count_ / std::max(1, num_subtests_called_) * 100
266         << "%"
267         << "\nGPUTOTAL failed rate: "
268         << setprecision(3) << (float)speedup_full_slower_count_ / std::max(1, num_subtests_called_) * 100
269         << "%"
270         << endl;
271     cout << resetiosflags(ios_base::fixed);
272 }
273
274
275 enum GTestColor {
276     COLOR_DEFAULT,
277     COLOR_RED,
278     COLOR_GREEN,
279     COLOR_YELLOW
280 };
281 #if GTEST_OS_WINDOWS&&!GTEST_OS_WINDOWS_MOBILE
282 // Returns the character attribute for the given color.
283 static WORD GetColorAttribute(GTestColor color) {
284     switch (color) {
285     case COLOR_RED:    return FOREGROUND_RED;
286     case COLOR_GREEN:  return FOREGROUND_GREEN;
287     case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
288     default:           return 0;
289     }
290 }
291 #else
292 static const char* GetAnsiColorCode(GTestColor color) {
293     switch (color) {
294     case COLOR_RED:     return "1";
295     case COLOR_GREEN:   return "2";
296     case COLOR_YELLOW:  return "3";
297     default:            return NULL;
298     };
299 }
300 #endif
301
302 static void printMetricsUti(double cpu_time, double gpu_time, double gpu_full_time, double speedup, double fullspeedup, std::stringstream& stream, std::stringstream& cur_subtest_description)
303 {
304     //cout <<TAB<< setw(7) << stream.str(); 
305     cout <<TAB; 
306
307     stream.str("");
308     stream << cpu_time;
309     cout << setw(10) << stream.str();
310
311     stream.str("");
312     stream << gpu_time;
313     cout << setw(10) << stream.str();
314
315     stream.str("");
316     stream << "x" << setprecision(3) << speedup;
317     cout << setw(8) << stream.str();
318
319     stream.str("");
320     stream << gpu_full_time;
321     cout << setw(10) << stream.str();
322
323     stream.str("");
324     stream << "x" << setprecision(3) << fullspeedup;
325     cout << setw(10) << stream.str();
326
327     cout << cur_subtest_description.str();
328     cout << resetiosflags(ios_base::left) << endl;
329 }
330
331 void TestSystem::printMetrics(int is_accurate, double cpu_time, double gpu_time, double gpu_full_time, double speedup, double fullspeedup)
332 {
333     cout << setiosflags(ios_base::left);
334     stringstream stream;
335
336     std::stringstream &cur_subtest_description = getCurSubtestDescription();
337    
338 #if GTEST_OS_WINDOWS&&!GTEST_OS_WINDOWS_MOBILE
339     
340     WORD color;
341     const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
342     // Gets the current text color.
343     CONSOLE_SCREEN_BUFFER_INFO buffer_info;
344     GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
345     const WORD old_color_attrs = buffer_info.wAttributes;
346     // We need to flush the stream buffers into the console before each
347     // SetConsoleTextAttribute call lest it affect the text that is already
348     // printed but has not yet reached the console.
349     fflush(stdout);
350
351     if(is_accurate == 1||is_accurate == -1)
352     {
353         color = old_color_attrs;
354         printMetricsUti(cpu_time, gpu_time, gpu_full_time, speedup, fullspeedup, stream, cur_subtest_description);
355
356     }else
357     {
358         color = GetColorAttribute(COLOR_RED);
359         SetConsoleTextAttribute(stdout_handle,
360             color| FOREGROUND_INTENSITY);
361
362         printMetricsUti(cpu_time, gpu_time, gpu_full_time, speedup, fullspeedup, stream, cur_subtest_description);
363         fflush(stdout);
364         // Restores the text color.
365         SetConsoleTextAttribute(stdout_handle, old_color_attrs);
366     }
367 #else
368     GTestColor color = COLOR_RED;
369     if(is_accurate == 1|| is_accurate == -1)
370     {
371         printMetricsUti(cpu_time, gpu_time, gpu_full_time, speedup, fullspeedup, stream, cur_subtest_description);
372
373     }else
374     {
375         printf("\033[0;3%sm", GetAnsiColorCode(color));
376         printMetricsUti(cpu_time, gpu_time, gpu_full_time, speedup, fullspeedup, stream, cur_subtest_description);
377         printf("\033[m");  // Resets the terminal to default.
378     }
379 #endif
380 }
381
382 void TestSystem::writeMetrics(double cpu_time, double gpu_time, double gpu_full_time, double speedup, double fullspeedup, double gpu_min, double gpu_max, double std_dev)
383 {
384     if (!record_)
385     {
386         recordname_ += ".csv";
387         record_ = fopen(recordname_.c_str(), "w");
388     }
389
390     string _is_accurate_;
391
392     if(is_accurate_ == 1)
393         _is_accurate_ = "Pass";
394     else if(is_accurate_ == 0)
395         _is_accurate_ = "Fail";
396     else if(is_accurate_ == -1)
397         _is_accurate_ = " ";
398     else
399     {
400         std::cout<<"is_accurate errer: "<<is_accurate_<<"\n";
401         exit(-1);
402     }
403
404     fprintf(record_, "%s,%s,%s,%.2f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f\n", 
405         itname_changed_ ? itname_.c_str() : "",
406         cur_subtest_description_.str().c_str(),
407         _is_accurate_.c_str(), 
408         accurate_diff_,
409         cpu_time, gpu_time, speedup, gpu_full_time, fullspeedup,
410         gpu_min, gpu_max, std_dev);
411
412     if (itname_changed_)
413     {
414         itname_changed_ = false;
415     }
416
417     fflush(record_);
418 }
419
420 void TestSystem::writeSummary()
421 {
422     if (!record_)
423     {
424         recordname_ += ".csv";
425         record_ = fopen(recordname_.c_str(), "w");
426     }
427
428     fprintf(record_, "\nAverage GPU speedup: %.3f\n"
429         "exceeded: %d (%.3f%%)\n"
430         "passed: %d (%.3f%%)\n"
431         "failed: %d (%.3f%%)\n"
432         "\nAverage GPUTOTAL speedup: %.3f\n"
433         "exceeded: %d (%.3f%%)\n"
434         "passed: %d (%.3f%%)\n"
435         "failed: %d (%.3f%%)\n",
436         speedup_total_ / std::max(1, num_subtests_called_),
437         speedup_faster_count_, (float)speedup_faster_count_ / std::max(1, num_subtests_called_) * 100,
438         speedup_equal_count_, (float)speedup_equal_count_ / std::max(1, num_subtests_called_) * 100,
439         speedup_slower_count_, (float)speedup_slower_count_ / std::max(1, num_subtests_called_) * 100,
440         speedup_full_total_ / std::max(1, num_subtests_called_),
441         speedup_full_faster_count_, (float)speedup_full_faster_count_ / std::max(1, num_subtests_called_) * 100,
442         speedup_full_equal_count_, (float)speedup_full_equal_count_ / std::max(1, num_subtests_called_) * 100,
443         speedup_full_slower_count_, (float)speedup_full_slower_count_ / std::max(1, num_subtests_called_) * 100
444         );
445     fflush(record_);
446 }
447
448 void TestSystem::printError(const std::string &msg)
449 {
450     if(msg != "CL_INVALID_BUFFER_SIZE")
451     {
452         cout << TAB << "[error: " << msg << "] " << cur_subtest_description_.str() << endl;
453     }
454 }
455
456 void gen(Mat &mat, int rows, int cols, int type, Scalar low, Scalar high)
457 {
458     mat.create(rows, cols, type);
459     RNG rng(0);
460     rng.fill(mat, RNG::UNIFORM, low, high);
461 }
462
463 string abspath(const string &relpath)
464 {
465     return TestSystem::instance().workingDir() + relpath;
466 }
467
468
469 int CV_CDECL cvErrorCallback(int /*status*/, const char * /*func_name*/,
470     const char *err_msg, const char * /*file_name*/,
471     int /*line*/, void * /*userdata*/)
472 {
473     TestSystem::instance().printError(err_msg);
474     return 0;
475 }
476
477 double checkNorm(const Mat &m)
478 {
479     return norm(m, NORM_INF);
480 }
481
482 double checkNorm(const Mat &m1, const Mat &m2)
483 {
484     return norm(m1, m2, NORM_INF);
485 }
486
487 double checkSimilarity(const Mat &m1, const Mat &m2)
488 {
489     Mat diff;
490     matchTemplate(m1, m2, diff, CV_TM_CCORR_NORMED);
491     return std::abs(diff.at<float>(0, 0) - 1.f);
492 }
493
494
495
496