SourceXtractorPlusPlus  0.10
Please provide a description of the project.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BenchConvolution.cpp
Go to the documentation of this file.
1 
17 /*
18  * Copyright (C) 2012-2020 Euclid Science Ground Segment
19  *
20  * This library is free software; you can redistribute it and/or modify it under
21  * the terms of the GNU Lesser General Public License as published by the Free
22  * Software Foundation; either version 3.0 of the License, or (at your option)
23  * any later version.
24  *
25  * This library is distributed in the hope that it will be useful, but WITHOUT
26  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
28  * details.
29  *
30  * You should have received a copy of the GNU Lesser General Public License
31  * along with this library; if not, write to the Free Software Foundation, Inc.,
32  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
41 #include <map>
42 #include <string>
43 
44 #include <boost/program_options.hpp>
45 #include <boost/timer/timer.hpp>
46 #include <random>
48 #include "ElementsKernel/Real.h"
49 #include "SEUtils/IsClose.h"
53 #ifdef WITH_OPENCV
55 #endif
56 
57 #if BOOST_VERSION < 105600
58 #include <boost/units/detail/utility.hpp>
59 using boost::units::detail::demangle;
60 #else
61 using boost::core::demangle;
62 #endif
63 
64 namespace po = boost::program_options;
65 namespace timer = boost::timer;
66 using namespace SourceXtractor;
67 
69 
71 private:
74 
75 public:
76 
77  po::options_description defineSpecificProgramOptions() override {
78  po::options_description options{};
79  options.add_options()
80  ("image-start", po::value<int>()->default_value(100), "Image start size")
81  ("kernel-start", po::value<int>()->default_value(3), "Kernel start size")
82  ("step-size", po::value<int>()->default_value(4), "Step size")
83  ("image-nsteps", po::value<int>()->default_value(1), "Number of steps for the image")
84  ("kernel-nsteps", po::value<int>()->default_value(2), "Number of steps for the kernel")
85  ("repeat", po::value<int>()->default_value(5), "Repeat")
86  ("measures", po::value<int>()->default_value(10), "Number of measures");
87  return options;
88  }
89 
91  auto img = VectorImage<SeFloat>::create(size, size);
92  for (int x = 0; x < size; ++x) {
93  for (int y = 0; y < size; ++y) {
94  img->setValue(x, y, random_dist(random_generator));
95  }
96  }
97  return img;
98  }
99 
101 
102  auto img_start = args["image-start"].as<int>();
103  auto krn_start = args["kernel-start"].as<int>();
104  auto step_size = args["step-size"].as<int>();
105  auto img_nsteps = args["image-nsteps"].as<int>();
106  auto krn_nsteps = args["kernel-nsteps"].as<int>();
107  auto repeat = args["repeat"].as<int>();
108  auto measures = args["measures"].as<int>();
109 
110  std::cout << "Image,Kernel,Implementation,Time" << std::endl;
111 
112  for (int img_step = 0; img_step < img_nsteps; ++img_step) {
113  auto img_size = img_start + img_step * step_size;
114  auto image = generateImage(img_size);
115 
116  for (int krn_step = 0; krn_step < krn_nsteps; ++krn_step) {
117  auto krn_size = krn_start + krn_step * step_size;
118 
119  logger.info() << "Using an image of " << img_size << "x" << img_size;
120  logger.info() << "Using a kernel of " << krn_size << "x" << krn_size;
121 
122  auto kernel = generateImage(krn_size);
123 
124 #ifdef WITH_OPENCV
125  logger.info() << "Timing OpenCV implementation";
126  auto opencv_result = benchmark<OpenCVConvolution>(image, kernel, repeat, measures);
127 #endif
128 
129  if (krn_size <= 10 || img_size <= 20) {
130  logger.info() << "Timing Direct implementation";
131  auto direct_result = benchmark<DirectConvolution<SeFloat>>(image, kernel, repeat, measures);
132 
133 #ifdef WITH_OPENCV
134  logger.info() << "Compare OpenCV vs Direct Result";
135  verifyResults(opencv_result, direct_result);
136 #endif
137  }
138 
139  logger.info() << "Timing DFT implementation";
140  auto dft_result = benchmark<DFTConvolution<SeFloat>>(image, kernel, repeat, measures);
141 
142 #ifdef WITH_OPENCV
143  logger.info() << "Compare OpenCV vs DFT Result";
144  verifyResults(opencv_result, dft_result);
145 #endif
146  }
147  }
148 
149  return Elements::ExitCode::OK;
150  }
151 
152  template<typename Convolution>
155  int repeat, int measures) {
156  auto conv_name = demangle(typeid(Convolution).name());
157 
158  Convolution convolution(kernel);
159 
161 
162  for (int m = 0; m < measures; ++m) {
163  logger.info() << conv_name << " " << m+1 << "/" << measures;
164  timer::cpu_timer timer;
165  timer.stop();
166 
167  for (int r = 0; r < repeat; ++r) {
168  copied = VectorImage<SeFloat>::create(*image);
169  timer.start();
170  convolution.convolve(copied);
171  timer.stop();
172  }
173 
174  std::cout << image->getWidth() << ',' << kernel->getWidth() << ",\"" << conv_name << "\"," << timer.elapsed().wall << std::endl;
175  }
176 
177  return copied;
178  }
179 
181  bool all_equal = true;
182  for (int x = 0; x < a->getWidth(); ++x) {
183  for (int y = 0; y < a->getHeight(); ++y) {
184  auto av = a->getValue(x, y);
185  auto bv = b->getValue(x, y);
186  if (!isClose(av, bv)) {
187  logger.info() << "Mismatch at " << x << ',' << y << ": "
188  << av << " != " << bv;
189  all_equal = false;
190  }
191  }
192  }
193  if (all_equal) {
194  logger.info() << "All elements are equal!";
195  }
196  else {
197  logger.warn() << "Convoluted images are not equal!";
198  }
199  }
200 };
201 
203 
204 
205 
po::options_description defineSpecificProgramOptions() override
static Elements::Logging logger
std::shared_ptr< VectorImage< SeFloat > > generateImage(int size)
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
T endl(T...args)
void info(const std::string &logMessage)
static std::shared_ptr< VectorImage< T > > create(Args &&...args)
Definition: VectorImage.h:89
bool isClose(double a, double b, double atol=1e-8, double rtol=1e-5)
Definition: IsClose.h:28
STL class.
std::shared_ptr< VectorImage< SeFloat > > benchmark(std::shared_ptr< VectorImage< SeFloat >> &image, std::shared_ptr< VectorImage< SeFloat >> &kernel, int repeat, int measures)
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
constexpr double m
Image implementation which keeps the pixel values in memory.
Definition: VectorImage.h:53
#define MAIN_FOR(ELEMENTS_PROGRAM_NAME)
void warn(const std::string &logMessage)
std::default_random_engine random_generator
Elements::ExitCode mainMethod(std::map< std::string, po::variable_value > &args) override
static Logging getLogger(const std::string &name="")
void verifyResults(std::shared_ptr< VectorImage< SeFloat >> a, std::shared_ptr< VectorImage< SeFloat >> b)