Optimized Belief Propagation (CPU and GPU)
RunImpOnInputBp.h
Go to the documentation of this file.
1 /*
2 Copyright (C) 2024 Scott Grauer-Gray
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
28 #include <array>
29 #include <map>
30 #include <memory>
31 #include <filesystem>
32 #include <optional>
33 #include <iostream>
38 #include "RunImp/RunImpOnInput.h"
43 
44 #ifndef RUN_IMP_ON_INPUT_BP_H_
45 #define RUN_IMP_ON_INPUT_BP_H_
46 
47 using filepathtype = std::filesystem::path;
48 
49 //check if optimized CPU run defined and make any necessary additions to support it
50 #if defined(OPTIMIZED_CPU_RUN)
51 //needed to run the optimized implementation a stereo set using CPU
53 //set RunBpOptimized alias to correspond to optimized CPU implementation
54 template <RunData_t T, unsigned int DISP_VALS, run_environment::AccSetting ACCELERATION>
56 #endif //OPTIMIZED_CPU_RUN
57 
58 //check if CUDA run defined and make any necessary additions to support it
59 #if defined(OPTIMIZED_CUDA_RUN)
60 //needed to run the implementation a stereo set using CUDA
62 //set RunBpOptimized alias to correspond to CUDA implementation
63 template <RunData_t T, unsigned int DISP_VALS, run_environment::AccSetting ACCELERATION>
65 #endif //OPTIMIZED_CUDA_RUN
66 
73 namespace bp_single_thread {
74 
77 constexpr bool kRunSingleThreadOnceForSet{true};
78 
81 inline std::map<std::array<filepathtype, 2>, std::tuple<std::chrono::duration<double>, RunData, filepathtype>>
83 
84 };
85 
94 template<RunData_t T, run_environment::AccSetting OPT_IMP_ACCEL, unsigned int NUM_INPUT>
95 class RunImpOnInputBp final : public RunImpOnInput<T, OPT_IMP_ACCEL, NUM_INPUT> {
96 public:
110  const run_environment::RunImpSettings& run_imp_settings) override;
111 
112 protected:
120  std::shared_ptr<ParallelParams> SetUpParallelParams(
121  const run_environment::RunImpSettings& run_imp_settings) const override;
122 
132  bool loop_iters_templated) const override;
133 
147  std::optional<RunData> RunImpsAndCompare(
148  std::shared_ptr<ParallelParams> parallel_params,
149  bool run_opt_imp_only,
150  bool run_imp_templated_loop_iters) const override;
151 
152 private:
155  std::unique_ptr<RunBpOnStereoSet<
156  T,
157  beliefprop::kStereoSetsToProcess[NUM_INPUT].num_disp_vals,
159  run_bp_stereo_single_thread_;
160 
163  std::unique_ptr<RunBpOnStereoSet<
164  T,
165  beliefprop::kStereoSetsToProcess[NUM_INPUT].num_disp_vals,
166  OPT_IMP_ACCEL>>
167  run_opt_bp_num_iters_templated_;
168 
171  std::unique_ptr<RunBpOnStereoSet<T, 0, OPT_IMP_ACCEL>>
172  run_opt_bp_num_iters_no_template_;
173 
175  beliefprop::BpSettings alg_settings_;
176 };
177 
178 //run and evaluate optimized belief propagation implementation on evaluation
179 //stereo set specified by NUM_INPUT
180 //data type used in implementation specified by T
181 //bp implemenation optimization specified by OPT_IMP_ACCEL
182 //evaluation stereo set to run implementation on specified by NUM_INPUT
183 template<RunData_t T, run_environment::AccSetting OPT_IMP_ACCEL, unsigned int NUM_INPUT>
185  const run_environment::RunImpSettings& run_imp_settings)
186 {
187  //set up BP settings for current run
188  alg_settings_.num_disp_vals =
189  beliefprop::kStereoSetsToProcess[NUM_INPUT].num_disp_vals;
190  alg_settings_.disc_k_bp =
191  (float)alg_settings_.num_disp_vals / 7.5f;
192 
193  //initialize run results across multiple implementations
194  MultRunData run_results;
195 
196  //set up unoptimized single threaded bp stereo implementation
197  run_bp_stereo_single_thread_ =
198  std::make_unique<RunBpOnStereoSetSingleThreadCPU<
199  T,
200  beliefprop::kStereoSetsToProcess[NUM_INPUT].num_disp_vals,
202 
203  //set up and run bp stereo using optimized implementation (optimized CPU and
204  //CUDA implementations supported) as well as unoptimized implementation for
205  //comparison
206  //run optimized implementation with and/or without disparity value count
207  //templated depending on setting
208  if (run_imp_settings.templated_iters_setting !=
210  {
211  run_opt_bp_num_iters_templated_ =
212  std::make_unique<RunBpOptimized<
213  T,
214  beliefprop::kStereoSetsToProcess[NUM_INPUT].num_disp_vals,
215  OPT_IMP_ACCEL>>();
216  constexpr bool run_w_loop_iters_templated{true};
217  InputSignature input_sig(
218  sizeof(T), NUM_INPUT, run_w_loop_iters_templated);
219  run_results.insert(
220  {input_sig,
221  this->RunEvalBenchmark(
222  run_imp_settings,
223  run_w_loop_iters_templated)});
224  }
225  if (run_imp_settings.templated_iters_setting !=
227  {
228  run_opt_bp_num_iters_no_template_ =
229  std::make_unique<RunBpOptimized<T, 0, OPT_IMP_ACCEL>>();
230  constexpr bool run_w_loop_iters_templated{false};
231  InputSignature input_sig(
232  sizeof(T), NUM_INPUT, run_w_loop_iters_templated);
233  run_results.insert(
234  {input_sig,
235  this->RunEvalBenchmark(
236  run_imp_settings,
237  run_w_loop_iters_templated)});
238  }
239 
240  //return bp run results across multiple implementations
241  return run_results;
242 }
243 
244 //set up parallel parameters for running belief propagation in parallel on
245 //CPU or GPU
246 template<RunData_t T, run_environment::AccSetting OPT_IMP_ACCEL, unsigned int NUM_INPUT>
247 std::shared_ptr<ParallelParams>
249  const run_environment::RunImpSettings& run_imp_settings) const
250 {
251  //parallel parameters initialized with default thread count dimensions at
252  //every level
253  return std::make_shared<ParallelParamsBp>(
254  run_imp_settings.opt_parallel_params_setting,
255  alg_settings_.num_levels,
256  run_imp_settings.p_params_default_alt_options.first);
257 }
258 
259 //get input data and parameter info about current benchmark (belief propagation
260 //in this case) and return as RunData type
261 template<RunData_t T, run_environment::AccSetting OPT_IMP_ACCEL, unsigned int NUM_INPUT>
263  bool loop_iters_templated) const
264 {
265  RunData curr_run_data;
266  curr_run_data.AddDataWHeader(
267  std::string(beliefprop::kStereoSetHeader),
268  std::string(beliefprop::kStereoSetsToProcess[NUM_INPUT].name));
269  curr_run_data.AppendData(this->InputAndParamsRunData(loop_iters_templated));
270  curr_run_data.AppendData(alg_settings_.AsRunData());
271  curr_run_data.AppendData(beliefprop::RunSettings());
272  return curr_run_data;
273 }
274 
275 //run and compare output disparity maps using the given optimized and
276 //single-threaded stereo implementations on the reference and test images
277 //specified by numStereoSet
278 //run only optimized implementation if run_opt_imp_only is true
279 template<RunData_t T, run_environment::AccSetting OPT_IMP_ACCEL, unsigned int NUM_INPUT>
281  std::shared_ptr<ParallelParams> parallel_params,
282  bool run_opt_imp_only,
283  bool run_imp_templated_loop_iters) const
284 {
285  //get properties of input stereo set from stereo set number
286  BpFileHandling bp_file_settings(
287  std::string(beliefprop::kStereoSetsToProcess[NUM_INPUT].name));
288  const std::array<filepathtype, 2> ref_test_image_path{
289  bp_file_settings.RefImagePath(),
290  bp_file_settings.TestImagePath()};
291 
292  //get number of implementations to run output disparity map file path(s)
293  //if run_opt_imp_only is false, run single-threaded implementation in
294  //addition to optimized implementation
295  const unsigned int num_imps_run{run_opt_imp_only ? 1u : 2u};
296  std::array<filepathtype, 2> output_disp;
297  for (unsigned int i=0; i < num_imps_run; i++) {
298  output_disp[i] =
300  }
301 
302  //get optimized implementation description and write info about run to
303  //std::cout stream
304  const std::string opt_imp_run_description{
305  run_imp_templated_loop_iters ?
306  run_opt_bp_num_iters_templated_->BpRunDescription() :
307  run_opt_bp_num_iters_no_template_->BpRunDescription()};
308  std::cout << "Running belief propagation on reference image "
309  << ref_test_image_path[0] << " and test image "
310  << ref_test_image_path[1] << " on " << opt_imp_run_description;
311  if (!run_opt_imp_only) {
312  std::cout << " and " << run_bp_stereo_single_thread_->BpRunDescription();
313  }
314  std::cout << std::endl;
315  std::cout << "Data size: " << sizeof(T) << std::endl;
316  std::cout << "run_imp_templated_loop_iters: " << run_imp_templated_loop_iters << std::endl;
317  std::cout << "Acceleration: " << run_environment::AccelerationString<OPT_IMP_ACCEL>() << std::endl;
318  std::cout << std::endl;
319 
320  //run optimized implementation and retrieve structure with runtime and output
321  //disparity map
322  std::map<run_environment::AccSetting, std::optional<beliefprop::BpRunOutput>>
323  run_output;
324  if (run_imp_templated_loop_iters) {
325  run_output[OPT_IMP_ACCEL] = run_opt_bp_num_iters_templated_->operator()(
326  {ref_test_image_path[0].string(), ref_test_image_path[1].string()},
327  alg_settings_,
328  *parallel_params);
329  }
330  else {
331  run_output[OPT_IMP_ACCEL] = run_opt_bp_num_iters_no_template_->operator()(
332  {ref_test_image_path[0].string(), ref_test_image_path[1].string()},
333  alg_settings_,
334  *parallel_params);
335  }
336 
337  //check if error in run
338  RunData run_data;
339  run_data.AddDataWHeader(
341  opt_imp_run_description);
342  if (!(run_output[OPT_IMP_ACCEL])) {
343  return {};
344  }
345 
346  //append implementation run data to evaluation run data
347  run_data.AppendData(run_output[OPT_IMP_ACCEL]->run_data);
348  run_data.AddDataWHeader(
350  run_output[OPT_IMP_ACCEL]->run_time.count());
351 
352  //save resulting disparity map
353  run_output[OPT_IMP_ACCEL]->out_disparity_map.SaveDisparityMap(
354  output_disp[0].string(),
355  beliefprop::kStereoSetsToProcess[NUM_INPUT].scale_factor);
356 
357  //check if only running optimized implementation or if also running
358  //single-threaded implementation
359  if (!run_opt_imp_only) {
360  //check if running single threaded implementation or using stored results
361  //from previous run
363  (!(bp_single_thread::single_thread_run_output.contains(ref_test_image_path))))
364  {
365  //run single-threaded implementation and retrieve structure with runtime
366  //and output disparity map
368  run_bp_stereo_single_thread_->operator()(
369  {ref_test_image_path[0].string(), ref_test_image_path[1].string()},
370  alg_settings_,
371  *parallel_params);
372  if (!(run_output[run_environment::AccSetting::kNone])) {
373  return {};
374  }
375 
376  //save resulting disparity map
377  run_output[run_environment::AccSetting::kNone]->out_disparity_map.SaveDisparityMap(
378  output_disp[1].string(),
379  beliefprop::kStereoSetsToProcess[NUM_INPUT].scale_factor);
380 
381  //save run data and result if setting to only run single thread
382  //implementation once for each set
385  {ref_test_image_path,
386  {run_output[run_environment::AccSetting::kNone]->run_time,
387  run_output[run_environment::AccSetting::kNone]->run_data,
388  output_disp[1]}});
389  }
390  }
391  else {
393  //retrieve stored results from previous run on single threaded implementation
394  run_output[run_environment::AccSetting::kNone]->run_time =
395  std::get<0>(bp_single_thread::single_thread_run_output.at(ref_test_image_path));
396  run_output[run_environment::AccSetting::kNone]->run_data =
397  std::get<1>(bp_single_thread::single_thread_run_output.at(ref_test_image_path));
398  run_output[run_environment::AccSetting::kNone]->out_disparity_map =
400  std::get<2>(bp_single_thread::single_thread_run_output.at(ref_test_image_path)).string(),
401  beliefprop::kStereoSetsToProcess[NUM_INPUT].scale_factor);
402  }
403  //append run data for single thread run to evaluation run data
404  run_data.AppendData(
405  run_output[run_environment::AccSetting::kNone]->run_data);
406  }
407 
408  //write location of output disparity maps for each implementation to std::cout
409  for (unsigned int i = 0; i < num_imps_run; i++) {
410  const std::string run_description{(i == 0) ?
411  opt_imp_run_description :
412  run_bp_stereo_single_thread_->BpRunDescription()};
413  std::cout << "Output disparity map from " << run_description
414  << " run at " << output_disp[i] << std::endl;
415  }
416  std::cout << std::endl;
417 
418  //compare resulting disparity maps with ground truth and to each other
419  const filepathtype ground_truth_disp{
420  bp_file_settings.GroundTruthDisparityFilePath()};
421  const DisparityMap<float> ground_truth_disparity_map(
422  ground_truth_disp.string(),
423  beliefprop::kStereoSetsToProcess[NUM_INPUT].scale_factor);
424  run_data.AddDataWHeader(
425  opt_imp_run_description + " output vs. Ground Truth result",
426  std::string());
427  run_data.AppendData(
428  run_output[OPT_IMP_ACCEL]->out_disparity_map.OutputComparison(
429  ground_truth_disparity_map,
431  if (!run_opt_imp_only) {
432  run_data.AddDataWHeader(
433  run_bp_stereo_single_thread_->BpRunDescription() + " output vs. Ground Truth result",
434  std::string());
435  run_data.AppendData(
436  run_output[run_environment::AccSetting::kNone]->out_disparity_map.OutputComparison(
437  ground_truth_disparity_map,
439  run_data.AddDataWHeader(
440  opt_imp_run_description + " output vs. " +
441  run_bp_stereo_single_thread_->BpRunDescription() + " result",
442  std::string());
443  run_data.AppendData(
444  run_output[OPT_IMP_ACCEL]->out_disparity_map.OutputComparison(
445  run_output[run_environment::AccSetting::kNone]->out_disparity_map,
447  }
448 
449  //return structure indicating that run succeeded along with data from run
450  return run_data;
451 }
452 
453 #endif //RUN_IMP_ON_INPUT_BP_H_
File with namespace for enums, constants, structures, and functions specific to belief propagation pr...
Header file that contains information about the stereo sets used for evaluation of the bp implementat...
Declares class to retrieve path of stereo set files for reading and for output.
std::map< InputSignature, std::optional< std::map< run_environment::ParallelParamsSetting, RunData > >> MultRunData
Alias mapping input signature to run data for each parallel parameters setting Run data is null if r...
Declares class for defining input signature for evaluation run that consists of evaluation set number...
Declares child class of RunBpOnStereoSet to run CUDA implementation of belief propagation on a given ...
Declares child class of RunBpOnStereoSet to run optimized CPU implementation of belief propagation on...
Contains namespace with enums and constants for implementation run evaluation.
Declares child class of RunImpOnInput to run and evaluate belief propagation implementation on a spec...
std::filesystem::path filepathtype
Declares and defines structure that stores settings for current implementation run as well as functio...
Define constraints for data type in processing.
Class to retrieve path of stereo set files for reading and for output.
std::filesystem::path RefImagePath() const
Return path to reference image with valid extension if found, otherwise throw filesystem error.
const std::filesystem::path GroundTruthDisparityFilePath() const
Get file path to ground truth disparity map.
const std::filesystem::path GetCurrentOutputDisparityFilePathAndIncrement()
Return path to use for current output disparity and then increment (to support multiple computed outp...
std::filesystem::path TestImagePath() const
Return path to test image with valid extension if found, otherwise throw filesystem error.
Class defines input signature for evaluation run that contains evaluation set number,...
Child class of RunBpOnStereoSet to run CUDA implementation of belief propagation on a given stereo se...
Abstract class to set up and run belief propagation on target device using specified acceleration.
Child class of RunBpOnStereoSet to run optimized CPU implementation of belief propagation on a given ...
Child class of RunBpOnStereoSet to run single-threaded CPU implementation of belief propagation on a ...
Definition: stereo.h:66
Class to store headers with data corresponding to current program run and evaluation.
Definition: RunData.h:42
void AppendData(const RunData &rundata)
Append current RunData with input RunData.
Definition: RunData.cpp:99
void AddDataWHeader(const std::string &header, const std::string &data)
Add string data with header describing added data.
Definition: RunData.cpp:49
Child class of RunImpOnInput to run and evaluate belief propagation implementation on a specified inp...
RunData InputAndParamsForCurrBenchmark(bool loop_iters_templated) const override
Get input data and parameter info about current benchmark (belief propagation in this case) and retur...
std::optional< RunData > RunImpsAndCompare(std::shared_ptr< ParallelParams > parallel_params, bool run_opt_imp_only, bool run_imp_templated_loop_iters) const override
Run and compare output disparity maps using the given optimized and single-threaded bp implementation...
std::shared_ptr< ParallelParams > SetUpParallelParams(const run_environment::RunImpSettings &run_imp_settings) const override
Set up parallel parameters for running belief propagation in parallel on CPU or GPU.
MultRunData operator()(const run_environment::RunImpSettings &run_imp_settings) override
Run and evaluate optimized belief propagation implementation on evaluation stereo set specified by NU...
Virtual class to run and evaluate implementation on a input specified by index number.
Definition: RunImpOnInput.h:53
constexpr std::string_view kStereoSetHeader
RunData RunSettings()
Retrieve run settings as a RunData object for output.
Definition: BpRunUtils.h:127
constexpr std::array< BpStereoSet, 8 > kStereoSetsToProcess
Declare stereo sets to process with name, num disparity values, and scale factor currently conesFullS...
Namespace with setting of whether or not to run single thread implementation a single time for each i...
constexpr bool kRunSingleThreadOnceForSet
Setting of whether or not to run single thread implementation once for each stereo set in evaluation.
std::map< std::array< filepathtype, 2 >, std::tuple< std::chrono::duration< double >, RunData, filepathtype > > single_thread_run_output
Map to store output and run results for single thread implementation for each stereo set.
constexpr std::string_view kAccelerationDescHeader
Constant string for acceleration.
constexpr std::string_view kOptimizedRuntimeHeader
Structure with output disparity map, runtime, and other evaluation data.
Structure to store the belief propagation settings including the number of levels and iterations.
Definition: BpSettings.h:87
Struct to store parameters for evaluation of disparity map from stereo processing.
Structure that stores settings for current implementation run.
Definition: RunSettings.h:84
TemplatedItersSetting templated_iters_setting
Definition: RunSettings.h:86
std::pair< std::array< unsigned int, 2 >, std::set< std::array< unsigned int, 2 > > > p_params_default_alt_options
Definition: RunSettings.h:89
OptParallelParamsSetting opt_parallel_params_setting
Definition: RunSettings.h:87