SourceXtractorPlusPlus 1.0.3
SourceXtractor++, the next generation SExtractor
Loading...
Searching...
No Matches
BenchConvolution.cpp
Go to the documentation of this file.
1
17
23
24#include <map>
25#include <string>
26
27#include <boost/program_options.hpp>
28#include <boost/timer/timer.hpp>
29#include <random>
30#include "ElementsKernel/ProgramHeaders.h"
31#include "ElementsKernel/Real.h"
32#include "SEUtils/IsClose.h"
36#ifdef WITH_OPENCV
38#endif
39
40#if BOOST_VERSION < 105600
41#include <boost/units/detail/utility.hpp>
42using boost::units::detail::demangle;
43#else
44using boost::core::demangle;
45#endif
46
47namespace po = boost::program_options;
48namespace timer = boost::timer;
49using namespace SourceXtractor;
50
52
54private:
57
58public:
59
60 po::options_description defineSpecificProgramOptions() override {
61 po::options_description options{};
62 options.add_options()
63 ("image-start", po::value<int>()->default_value(100), "Image start size")
64 ("kernel-start", po::value<int>()->default_value(3), "Kernel start size")
65 ("step-size", po::value<int>()->default_value(4), "Step size")
66 ("image-nsteps", po::value<int>()->default_value(1), "Number of steps for the image")
67 ("kernel-nsteps", po::value<int>()->default_value(2), "Number of steps for the kernel")
68 ("repeat", po::value<int>()->default_value(5), "Repeat")
69 ("measures", po::value<int>()->default_value(10), "Number of measures");
70 return options;
71 }
72
74 auto img = VectorImage<SeFloat>::create(size, size);
75 for (int x = 0; x < size; ++x) {
76 for (int y = 0; y < size; ++y) {
77 img->setValue(x, y, random_dist(random_generator));
78 }
79 }
80 return img;
81 }
82
84
85 auto img_start = args["image-start"].as<int>();
86 auto krn_start = args["kernel-start"].as<int>();
87 auto step_size = args["step-size"].as<int>();
88 auto img_nsteps = args["image-nsteps"].as<int>();
89 auto krn_nsteps = args["kernel-nsteps"].as<int>();
90 auto repeat = args["repeat"].as<int>();
91 auto measures = args["measures"].as<int>();
92
93 std::cout << "Image,Kernel,Implementation,Time" << std::endl;
94
95 for (int img_step = 0; img_step < img_nsteps; ++img_step) {
96 auto img_size = img_start + img_step * step_size;
97 auto image = generateImage(img_size);
98
99 for (int krn_step = 0; krn_step < krn_nsteps; ++krn_step) {
100 auto krn_size = krn_start + krn_step * step_size;
101
102 logger.info() << "Using an image of " << img_size << "x" << img_size;
103 logger.info() << "Using a kernel of " << krn_size << "x" << krn_size;
104
105 auto kernel = generateImage(krn_size);
106
107#ifdef WITH_OPENCV
108 logger.info() << "Timing OpenCV implementation";
109 auto opencv_result = benchmark<OpenCVConvolution>(image, kernel, repeat, measures);
110#endif
111
112 if (krn_size <= 10 || img_size <= 20) {
113 logger.info() << "Timing Direct implementation";
114 auto direct_result = benchmark<DirectConvolution<SeFloat>>(image, kernel, repeat, measures);
115
116#ifdef WITH_OPENCV
117 logger.info() << "Compare OpenCV vs Direct Result";
118 verifyResults(opencv_result, direct_result);
119#endif
120 }
121
122 logger.info() << "Timing DFT implementation";
123 auto dft_result = benchmark<DFTConvolution<SeFloat>>(image, kernel, repeat, measures);
124
125#ifdef WITH_OPENCV
126 logger.info() << "Compare OpenCV vs DFT Result";
127 verifyResults(opencv_result, dft_result);
128#endif
129 }
130 }
131
133 }
134
135 template<typename Convolution>
138 int repeat, int measures) {
139 auto conv_name = demangle(typeid(Convolution).name());
140
141 Convolution convolution(kernel);
142
144
145 for (int m = 0; m < measures; ++m) {
146 logger.info() << conv_name << " " << m+1 << "/" << measures;
147 timer::cpu_timer timer;
148 timer.stop();
149
150 for (int r = 0; r < repeat; ++r) {
151 copied = VectorImage<SeFloat>::create(*image);
152 timer.start();
153 convolution.convolve(copied);
154 timer.stop();
155 }
156
157 std::cout << image->getWidth() << ',' << kernel->getWidth() << ",\"" << conv_name << "\"," << timer.elapsed().wall << std::endl;
158 }
159
160 return copied;
161 }
162
164 bool all_equal = true;
165 for (int x = 0; x < a->getWidth(); ++x) {
166 for (int y = 0; y < a->getHeight(); ++y) {
167 auto av = a->getValue(x, y);
168 auto bv = b->getValue(x, y);
169 if (!isClose(av, bv)) {
170 logger.info() << "Mismatch at " << x << ',' << y << ": "
171 << av << " != " << bv;
172 all_equal = false;
173 }
174 }
175 }
176 if (all_equal) {
177 logger.info() << "All elements are equal!";
178 }
179 else {
180 logger.warn() << "Convoluted images are not equal!";
181 }
182 }
183};
184
186
187
188
static Elements::Logging logger
std::shared_ptr< VectorImage< SeFloat > > benchmark(std::shared_ptr< VectorImage< SeFloat > > &image, std::shared_ptr< VectorImage< SeFloat > > &kernel, int repeat, int measures)
Elements::ExitCode mainMethod(std::map< std::string, po::variable_value > &args) override
po::options_description defineSpecificProgramOptions() override
void verifyResults(std::shared_ptr< VectorImage< SeFloat > > a, std::shared_ptr< VectorImage< SeFloat > > b)
std::shared_ptr< VectorImage< SeFloat > > generateImage(int size)
std::uniform_real_distribution< SeFloat > random_dist
std::default_random_engine random_generator
static Logging getLogger(const std::string &name="")
Image implementation which keeps the pixel values in memory.
Definition VectorImage.h:52
static std::shared_ptr< VectorImage< T > > create(Args &&... args)
T endl(T... args)
#define MAIN_FOR(ELEMENTS_PROGRAM_NAME)
static Elements::Logging logger
bool isClose(double a, double b, double atol=1e-8, double rtol=1e-5)
Definition IsClose.h:28