Optimized Belief Propagation (CPU and GPU)
ProcessBp.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 
29 #ifndef PROCESS_BP_H_
30 #define PROCESS_BP_H_
31 
32 #include <math.h>
33 #include <chrono>
34 #include <unordered_map>
35 #include <memory>
36 #include <vector>
37 #include <array>
38 #include <utility>
39 #include <ranges>
48 #include "BpSettings.h"
49 #include "BpRunUtils.h"
50 #include "ParallelParamsBp.h"
51 #include "BpLevel.h"
52 
55 using timingType = std::chrono::time_point<std::chrono::system_clock>;
56 
66 template<RunData_t T, unsigned int DISP_VALS, run_environment::AccSetting ACCELERATION>
67 class ProcessBp {
68 public:
69  explicit ProcessBp(
70  const ParallelParams& parallel_params) :
71  parallel_params_{parallel_params} {}
72 
74  const char *file = "",
75  int line = 0,
76  bool abort = false) const
77  {
79  }
80 
95  std::optional<std::pair<float*, DetailedTimings<beliefprop::Runtime_Type>>> operator()(
96  const std::array<float*, 2>& images_target_device,
97  const beliefprop::BpSettings& alg_settings,
98  const std::array<unsigned int, 2>& width_height_images,
99  T* allocated_mem_bp_processing, T* allocated_memory,
100  const std::unique_ptr<MemoryManagement<T>>& mem_management_bp_run) const;
101 
102 protected:
104 
105 private:
115  virtual run_eval::Status InitializeDataCosts(
116  const beliefprop::BpSettings& alg_settings,
117  const BpLevel<T>& current_bp_level,
118  const std::array<float*, 2>& images_target_device,
119  const beliefprop::DataCostsCheckerboards<T*>& data_costs_device) const = 0;
120 
131  virtual run_eval::Status InitializeDataCurrentLevel(
132  const BpLevel<T>& current_bp_level,
133  const BpLevel<T>& prev_bp_level,
134  const beliefprop::DataCostsCheckerboards<T*>& data_costs_device,
135  const beliefprop::DataCostsCheckerboards<T*>& data_costs_device_write,
136  unsigned int bp_settings_num_disp_vals) const = 0;
137 
146  virtual run_eval::Status InitializeMessageValsToDefault(
147  const BpLevel<T>& current_bp_level,
148  const beliefprop::CheckerboardMessages<T*>& messages_device,
149  unsigned int bp_settings_num_disp_vals) const = 0;
150 
161  virtual run_eval::Status RunBPAtCurrentLevel(
162  const beliefprop::BpSettings& alg_settings,
163  const BpLevel<T>& current_bp_level,
164  const beliefprop::DataCostsCheckerboards<T*>& data_costs_device,
165  const beliefprop::CheckerboardMessages<T*>& messages_device,
166  T* allocated_memory) const = 0;
167 
178  virtual run_eval::Status CopyMessageValuesToNextLevelDown(
179  const BpLevel<T>& current_bp_level,
180  const BpLevel<T>& next_bp_level,
181  const beliefprop::CheckerboardMessages<T*>& messages_device_copy_from,
182  const beliefprop::CheckerboardMessages<T*>& messages_device_copy_to,
183  unsigned int bp_settings_num_disp_vals) const = 0;
184 
195  virtual float* RetrieveOutputDisparity(
196  const BpLevel<T>& BpLevel,
197  const beliefprop::DataCostsCheckerboards<T*>& data_costs_device,
198  const beliefprop::CheckerboardMessages<T*>& messages_device,
199  unsigned int bp_settings_num_disp_vals) const = 0;
200 
207  virtual void FreeCheckerboardMessagesMemory(
208  const beliefprop::CheckerboardMessages<T*>& checkerboard_messages_to_free,
209  const std::unique_ptr<MemoryManagement<T>>& mem_management_bp_run) const
210  {
211  std::ranges::for_each(checkerboard_messages_to_free,
212  [&mem_management_bp_run](auto& checkerboard_messages_set) {
213  std::ranges::for_each(checkerboard_messages_set,
214  [&mem_management_bp_run](auto& checkerboard_messages) {
215  mem_management_bp_run->FreeAlignedMemoryOnDevice(checkerboard_messages);
216  });
217  });
218  }
219 
228  virtual beliefprop::CheckerboardMessages<T*> AllocateMemoryForCheckerboardMessages(
229  std::size_t num_data_allocate_per_message,
230  const std::unique_ptr<MemoryManagement<T>>& mem_management_bp_run) const
231  {
232  beliefprop::CheckerboardMessages<T*> output_checkerboard_messages;
233  std::ranges::for_each(
234  output_checkerboard_messages,
235  [this, num_data_allocate_per_message, &mem_management_bp_run](
236  auto& checkerboard_messages_set)
237  {
238  std::ranges::for_each(checkerboard_messages_set,
239  [this, num_data_allocate_per_message, &mem_management_bp_run](
240  auto& checkerboard_messages)
241  {
242  checkerboard_messages =
243  mem_management_bp_run->AllocateAlignedMemoryOnDevice(
244  num_data_allocate_per_message,
245  ACCELERATION);
246  });
247  }
248  );
249 
250  return output_checkerboard_messages;
251  }
252 
262  virtual beliefprop::CheckerboardMessages<T*> RetrieveLevelMessageData(
263  const beliefprop::CheckerboardMessages<T*>& all_checkerboard_messages,
264  std::size_t offset_into_messages) const
265  {
266  beliefprop::CheckerboardMessages<T*> output_checkerboard_messages;
267  for (const auto checkerboard_num :
268  {static_cast<unsigned int>(beliefprop::CheckerboardPart::kCheckerboardPart0),
269  static_cast<unsigned int>(beliefprop::CheckerboardPart::kCheckerboardPart1)})
270  {
271  for (unsigned int i = 0;
272  i < output_checkerboard_messages[checkerboard_num].size();
273  i++)
274  {
275  output_checkerboard_messages[checkerboard_num][i] =
276  &((all_checkerboard_messages[checkerboard_num][i])[offset_into_messages]);
277  }
278  }
279 
280  return output_checkerboard_messages;
281  }
282 
289  virtual void FreeDataCostsMemory(
290  const beliefprop::DataCostsCheckerboards<T*>& data_costs_to_free,
291  const std::unique_ptr<MemoryManagement<T>>& mem_management_bp_run) const
292  {
293  mem_management_bp_run->FreeAlignedMemoryOnDevice(data_costs_to_free[0]);
294  mem_management_bp_run->FreeAlignedMemoryOnDevice(data_costs_to_free[1]);
295  }
296 
305  virtual beliefprop::DataCostsCheckerboards<T*> AllocateMemoryForDataCosts(
306  std::size_t num_data_costs_checkerboards,
307  const std::unique_ptr<MemoryManagement<T>>& mem_management_bp_run) const
308  {
309  return {mem_management_bp_run->AllocateAlignedMemoryOnDevice(
310  num_data_costs_checkerboards,
311  ACCELERATION),
312  mem_management_bp_run->AllocateAlignedMemoryOnDevice(
313  num_data_costs_checkerboards,
314  ACCELERATION)};
315  }
316 
326  virtual std::pair<beliefprop::DataCostsCheckerboards<T*>, beliefprop::CheckerboardMessages<T*>>
327  AllocateAndOrganizeDataCostsAndMessageDataAllLevels(
328  std::size_t num_data_allocate_per_data_costs_message_data_array,
329  const std::unique_ptr<MemoryManagement<T>>& mem_management_bp_run) const
330  {
331  T* data_all_levels = mem_management_bp_run->AllocateAlignedMemoryOnDevice(
332  10*num_data_allocate_per_data_costs_message_data_array, ACCELERATION);
333  return OrganizeDataCostsAndMessageDataAllLevels(
334  data_all_levels, num_data_allocate_per_data_costs_message_data_array);
335  }
336 
345  virtual std::pair<beliefprop::DataCostsCheckerboards<T*>, beliefprop::CheckerboardMessages<T*>>
346  OrganizeDataCostsAndMessageDataAllLevels(
347  T* data_all_levels, std::size_t num_data_allocate_per_data_costs_message_data_array) const
348  {
349  beliefprop::DataCostsCheckerboards<T*> data_costs_device_checkerboard_all_levels;
350  data_costs_device_checkerboard_all_levels[0] = data_all_levels;
351  data_costs_device_checkerboard_all_levels[1] =
352  &(data_costs_device_checkerboard_all_levels[0][1 * (num_data_allocate_per_data_costs_message_data_array)]);
353 
354  beliefprop::CheckerboardMessages<T*> messages_device_all_levels;
355  for (const auto checkerboard_num :
356  {static_cast<unsigned int>(beliefprop::CheckerboardPart::kCheckerboardPart0),
357  static_cast<unsigned int>(beliefprop::CheckerboardPart::kCheckerboardPart1)})
358  {
359  for (unsigned int i = 0;
360  i < messages_device_all_levels[checkerboard_num].size();
361  i++)
362  {
363  messages_device_all_levels[checkerboard_num][i] =
364  &(data_costs_device_checkerboard_all_levels[0][
365  ((checkerboard_num * messages_device_all_levels[checkerboard_num].size()) + (i + 2)) *
366  (num_data_allocate_per_data_costs_message_data_array)]);
367  }
368  }
369 
370  return {data_costs_device_checkerboard_all_levels, messages_device_all_levels};
371  }
372 
380  virtual void FreeDataCostsAllDataInSingleArray(
381  const beliefprop::DataCostsCheckerboards<T*>& data_costs_to_free,
382  const std::unique_ptr<MemoryManagement<T>>& mem_management_bp_run) const
383  {
384  mem_management_bp_run->FreeAlignedMemoryOnDevice(data_costs_to_free[0]);
385  }
386 
395  virtual beliefprop::DataCostsCheckerboards<T*> RetrieveLevelDataCosts(
396  const beliefprop::DataCostsCheckerboards<T*>& all_data_costs,
397  std::size_t offset) const
398  {
399  return {&(all_data_costs[0][offset]),
400  &(all_data_costs[1][offset])};
401  }
402 };
403 
404 //run the belief propagation algorithm with on a set of stereo images to
405 //generate a disparity map on target device
406 //input is images on target device for computation
407 //output is disparity map and processing runtimes
408 template<RunData_t T, unsigned int DISP_VALS, run_environment::AccSetting ACCELERATION>
409 std::optional<std::pair<float*, DetailedTimings<beliefprop::Runtime_Type>>>
411  const std::array<float*, 2> & images_target_device,
412  const beliefprop::BpSettings& alg_settings,
413  const std::array<unsigned int, 2>& width_height_images,
414  T* allocated_mem_bp_processing,
415  T* allocated_memory,
416  const std::unique_ptr<MemoryManagement<T>>& mem_management_bp_run) const
417 {
418  if (ErrorCheck() != run_eval::Status::kNoError) { return {}; }
419 
420  std::unordered_map<beliefprop::Runtime_Type, std::array<timingType, 2>> start_end_times;
421  std::vector<std::array<timingType, 2>> data_costs_timings(alg_settings.num_levels);
422  std::vector<std::array<timingType, 2>> bp_timings(alg_settings.num_levels);
423  std::vector<std::array<timingType, 2>> data_copy_timings(alg_settings.num_levels);
424  std::chrono::duration<double> total_time_bp_iters{0};
425  std::chrono::duration<double> total_time_copy_data{0};
426  std::chrono::duration<double> total_time_copy_data_kernel{0};
427 
428  //start at the "bottom level" and work way up to determine amount of space
429  //needed to store data costs
430  std::vector<BpLevel<T>> bp_levels;
431  bp_levels.reserve(alg_settings.num_levels);
432 
433  //set level properties for bottom level that include processing of full image
434  //width/height
435  bp_levels.push_back(BpLevel<T>(width_height_images, 0, 0, ACCELERATION));
436 
437  //compute level properties which includes offset for each data/message array
438  //for each level after the bottom level
439  for (unsigned int level_num = 1;
440  level_num < alg_settings.num_levels;
441  level_num++)
442  {
443  //get current level properties from previous level properties
444  bp_levels.push_back(
445  bp_levels[level_num-1].NextBpLevel(alg_settings.num_disp_vals));
446  }
447 
449  std::chrono::system_clock::now();
450 
451  //declare and allocate the space on the device to store the data cost
452  //component at each possible movement at each level of the "pyramid" as well
453  //as the message data used for bp processing
454  //each checkerboard holds half of the data and checkerboard 0 includes the
455  //pixel in slot (0, 0)
456  beliefprop::DataCostsCheckerboards<T*> data_costs_device_all_levels;
457  beliefprop::CheckerboardMessages<T*> messages_device_all_levels;
458 
459  //data for each array at all levels set to data up to final level
460  //(corresponds to offset at final level) plus data amount at final level
461  const std::size_t data_all_levels_each_data_message_arr =
462  bp_levels[alg_settings.num_levels-1].LevelProperties().offset_into_arrays_ +
463  bp_levels[alg_settings.num_levels-1].NumDataInBpArrays(alg_settings.num_disp_vals);
464 
465  //assuming that width includes padding
466  if constexpr (beliefprop::kUseOptMemManagement) {
468  std::tie(data_costs_device_all_levels, messages_device_all_levels) =
469  OrganizeDataCostsAndMessageDataAllLevels(
470  allocated_mem_bp_processing, data_all_levels_each_data_message_arr);
471  }
472  else {
473  //call function that allocates all data in single array and then
474  //set offsets in array for data costs and message data locations
475  std::tie(data_costs_device_all_levels, messages_device_all_levels) =
476  AllocateAndOrganizeDataCostsAndMessageDataAllLevels(
477  data_all_levels_each_data_message_arr, mem_management_bp_run);
478  }
479  }
480  else {
481  data_costs_device_all_levels =
482  AllocateMemoryForDataCosts(
483  data_all_levels_each_data_message_arr,
484  mem_management_bp_run);
485  }
486 
487  auto curr_time = std::chrono::system_clock::now();
488  start_end_times[beliefprop::Runtime_Type::kInitSettingsMalloc][1] = curr_time;
489  data_costs_timings[0][0] = curr_time;
490 
491  //initialize the data cost at the bottom level
492  auto error_code =
493  InitializeDataCosts(
494  alg_settings,
495  bp_levels[0],
496  images_target_device,
497  data_costs_device_all_levels);
498  if (error_code != run_eval::Status::kNoError) { return {}; }
499 
500  curr_time = std::chrono::system_clock::now();
501  data_costs_timings[0][1] = curr_time;
502  start_end_times[beliefprop::Runtime_Type::kDataCostsHigherLevel][0] = curr_time;
503 
504  //set the data costs at each level from the bottom level "up"
505  for (unsigned int level_num = 1u; level_num < alg_settings.num_levels; level_num++)
506  {
507  data_costs_timings[level_num][0] = std::chrono::system_clock::now();
508  error_code =
509  InitializeDataCurrentLevel(
510  bp_levels[level_num],
511  bp_levels[level_num - 1],
512  RetrieveLevelDataCosts(
513  data_costs_device_all_levels,
514  bp_levels[level_num - 1u].LevelProperties().offset_into_arrays_),
515  RetrieveLevelDataCosts(
516  data_costs_device_all_levels,
517  bp_levels[level_num].LevelProperties().offset_into_arrays_),
518  alg_settings.num_disp_vals);
519  if (error_code != run_eval::Status::kNoError) { return {}; }
520 
521  data_costs_timings[level_num][1] = std::chrono::system_clock::now();
522  }
523 
524  curr_time = data_costs_timings[alg_settings.num_levels-1][1];
525  start_end_times[beliefprop::Runtime_Type::kDataCostsHigherLevel][1] = curr_time;
526  start_end_times[beliefprop::Runtime_Type::kInitMessages][0] = curr_time;
527 
528  //get and use offset into data at current processing level of pyramid
529  beliefprop::DataCostsCheckerboards<T*> data_costs_device_current_level =
530  RetrieveLevelDataCosts(
531  data_costs_device_all_levels,
532  bp_levels[alg_settings.num_levels - 1u].LevelProperties().offset_into_arrays_);
533 
534  //declare the space for two levels of BP messages
535  //need to support two "sets" of checkerboards because the message data at the
536  //current level
537  //in the image pyramid need copied to a lower level without overwriting values
538  std::array<beliefprop::CheckerboardMessages<T*>, 2> messages_curr_next_level;
539 
540  //alternate between indices 0 and 1 for current and next level messages sets
541  //in messages for bp level array
542  unsigned int current_level_messages_idx{0};
543  unsigned int next_level_messages_idx{(current_level_messages_idx + 1) % 2};
544 
545  //assuming that width includes padding
546  if constexpr (beliefprop::kUseOptMemManagement) {
547  messages_curr_next_level[current_level_messages_idx] =
548  RetrieveLevelMessageData(
549  messages_device_all_levels,
550  bp_levels[alg_settings.num_levels - 1u].LevelProperties().offset_into_arrays_);
551  }
552  else {
553  //allocate the space for the message values in the first checkboard set at
554  //the current level
555  messages_curr_next_level[current_level_messages_idx] =
556  AllocateMemoryForCheckerboardMessages(
557  bp_levels[alg_settings.num_levels - 1u].NumDataInBpArrays(alg_settings.num_disp_vals),
558  mem_management_bp_run);
559  }
560 
562  std::chrono::system_clock::now();
563 
564  //initialize all the BP message values at every pixel for every disparity to 0
565  error_code =
566  InitializeMessageValsToDefault(
567  bp_levels[alg_settings.num_levels - 1],
568  messages_curr_next_level[current_level_messages_idx],
569  alg_settings.num_disp_vals);
570  if (error_code != run_eval::Status::kNoError) { return {}; }
571 
572  curr_time = std::chrono::system_clock::now();
573  start_end_times[beliefprop::Runtime_Type::kInitMessagesKernel][1] = curr_time;
574  start_end_times[beliefprop::Runtime_Type::kInitMessages][1] = curr_time;
575 
576  //run BP at each level in the "pyramid" starting on top and continuing to the
577  //bottom where the final movement values are computed...the message values
578  //are passed from the upper level to the lower levels; this pyramid methods
579  //causes the BP message values to converge more quickly
580  for (int level_num = (int)alg_settings.num_levels - 1;
581  level_num >= 0;
582  level_num--)
583  {
584  const auto bp_iter_start_time = std::chrono::system_clock::now();
585 
586  //alternate which checkerboard messages set to use for each level
587  //to support copying from one to the other in parallel
588  //without read-write conflicts
589  error_code =
590  RunBPAtCurrentLevel(
591  alg_settings,
592  bp_levels[(unsigned int)level_num],
593  data_costs_device_current_level,
594  messages_curr_next_level[current_level_messages_idx],
595  allocated_memory);
596  if (error_code != run_eval::Status::kNoError) { return {}; }
597 
598  //retrieve and update total run time for bp processing at levels
599  const auto bp_iter_end_time = std::chrono::system_clock::now();
600  total_time_bp_iters += bp_iter_end_time - bp_iter_start_time;
601  const auto copy_message_values_start_time = std::chrono::system_clock::now();
602 
603  //if not at the "bottom level" copy the current message values at the
604  //current level to the corresponding slots next level
605  if (level_num > 0)
606  {
607  //use offset into allocated memory at next level
608  data_costs_device_current_level =
609  RetrieveLevelDataCosts(
610  data_costs_device_all_levels,
611  bp_levels[level_num - 1].LevelProperties().offset_into_arrays_);
612 
613  //assuming that width includes padding
614  if constexpr (beliefprop::kUseOptMemManagement) {
615  messages_curr_next_level[next_level_messages_idx] =
616  RetrieveLevelMessageData(
617  messages_device_all_levels,
618  bp_levels[level_num - 1].LevelProperties().offset_into_arrays_);
619  }
620  else {
621  //allocate space for the message values in the next level
622  messages_curr_next_level[next_level_messages_idx] =
623  AllocateMemoryForCheckerboardMessages(
624  bp_levels[level_num - 1].NumDataInBpArrays(alg_settings.num_disp_vals));
625  }
626 
627  const auto copy_message_values_kernel_start_time = std::chrono::system_clock::now();
628 
629  //copying messages values from messages_curr_next_level[current_level_messages_idx]
630  //to messages_curr_next_level[next_levels_messages_idx]
631  //current_level_messages_idx is later set to next_levels_messages_idx when processing next level
632  error_code =
633  CopyMessageValuesToNextLevelDown(
634  bp_levels[level_num],
635  bp_levels[level_num - 1],
636  messages_curr_next_level[current_level_messages_idx],
637  messages_curr_next_level[next_level_messages_idx],
638  alg_settings.num_disp_vals);
639  if (error_code != run_eval::Status::kNoError) { return {}; }
640 
641  //get timing of copying bp message values to next level
642  const auto copy_message_values_kernel_end_time = std::chrono::system_clock::now();
643  total_time_copy_data_kernel +=
644  copy_message_values_kernel_end_time - copy_message_values_kernel_start_time;
645  data_copy_timings[level_num][0] = copy_message_values_kernel_start_time;
646  data_copy_timings[level_num][1] = copy_message_values_kernel_end_time;
647 
648  if constexpr (!beliefprop::kUseOptMemManagement) {
649  //free the now-copied from computed data of the completed level
650  FreeCheckerboardMessagesMemory(
651  messages_curr_next_level[current_level_messages_idx],
652  mem_management_bp_run);
653  }
654 
655  //update current and next level messages indices for processing at next
656  //level; specifically indices of each are swapped with each other
657  //where one level has an index values of 0 and the other one has an index
658  //value of 1
659  current_level_messages_idx = (current_level_messages_idx + 1) % 2;
660  next_level_messages_idx = (current_level_messages_idx + 1) % 2;
661  }
662 
663  //update total timing for copying messages and bp timing at level
664  const auto copy_message_values_end_time = std::chrono::system_clock::now();
665  total_time_copy_data +=
666  copy_message_values_end_time - copy_message_values_start_time;
667  bp_timings[level_num][0] = bp_iter_start_time;
668  bp_timings[level_num][1] = bp_iter_end_time;
669  }
670 
671  start_end_times[beliefprop::Runtime_Type::kOutputDisparity][0] =
672  std::chrono::system_clock::now();
673 
674  //assume in bottom level when retrieving output disparity
675  float* result_disp_map_device =
677  bp_levels[0],
678  data_costs_device_current_level,
679  messages_curr_next_level[current_level_messages_idx],
680  alg_settings.num_disp_vals);
681  if (result_disp_map_device == nullptr) { return {}; }
682 
683  curr_time = std::chrono::system_clock::now();
684  start_end_times[beliefprop::Runtime_Type::kOutputDisparity][1] = curr_time;
685  start_end_times[beliefprop::Runtime_Type::kFinalFree][0] = curr_time;
686 
687  if constexpr (beliefprop::kUseOptMemManagement) {
689  //do nothing; memory freed outside of runs
690  }
691  else {
692  //now free the allocated data space; all data in single array when
693  //beliefprop::kUseOptMemManagement set to true
694  FreeDataCostsAllDataInSingleArray(
695  data_costs_device_all_levels,
696  mem_management_bp_run);
697  }
698  }
699  else {
700  //free the device storage allocated to the message values used to retrieve
701  //the output movement values
702  FreeCheckerboardMessagesMemory(
703  messages_curr_next_level[current_level_messages_idx],
704  mem_management_bp_run);
705 
706  //now free the allocated data space
707  FreeDataCostsMemory(
708  data_costs_device_all_levels,
709  mem_management_bp_run);
710  }
711 
712  start_end_times[beliefprop::Runtime_Type::kFinalFree][1] =
713  std::chrono::system_clock::now();
714 
715  //retrieve and store processing runtimes for bp at each level
716  //currently a maximum of 10 levels is supported
717  start_end_times[beliefprop::Runtime_Type::kLevel0DataCosts] = data_costs_timings[0];
718  start_end_times[beliefprop::Runtime_Type::kLevel0Bp] = bp_timings[0];
719  start_end_times[beliefprop::Runtime_Type::kLevel0Copy] = data_copy_timings[0];
720  if (bp_timings.size() > 1) {
721  start_end_times[beliefprop::Runtime_Type::kLevel1DataCosts] = data_costs_timings[1];
722  start_end_times[beliefprop::Runtime_Type::kLevel1Bp] = bp_timings[1];
723  start_end_times[beliefprop::Runtime_Type::kLevel1Copy] = data_copy_timings[1];
724  }
725  if (bp_timings.size() > 2) {
726  start_end_times[beliefprop::Runtime_Type::kLevel2DataCosts] = data_costs_timings[2];
727  start_end_times[beliefprop::Runtime_Type::kLevel2Bp] = bp_timings[2];
728  start_end_times[beliefprop::Runtime_Type::kLevel2Copy] = data_copy_timings[2];
729  }
730  if (bp_timings.size() > 3) {
731  start_end_times[beliefprop::Runtime_Type::kLevel3DataCosts] = data_costs_timings[3];
732  start_end_times[beliefprop::Runtime_Type::kLevel3Bp] = bp_timings[3];
733  start_end_times[beliefprop::Runtime_Type::kLevel3Copy] = data_copy_timings[3];
734  }
735  if (bp_timings.size() > 4) {
736  start_end_times[beliefprop::Runtime_Type::kLevel4DataCosts] = data_costs_timings[4];
737  start_end_times[beliefprop::Runtime_Type::kLevel4Bp] = bp_timings[4];
738  start_end_times[beliefprop::Runtime_Type::kLevel4Copy] = data_copy_timings[4];
739  }
740  if (bp_timings.size() > 5) {
741  start_end_times[beliefprop::Runtime_Type::kLevel5DataCosts] = data_costs_timings[5];
742  start_end_times[beliefprop::Runtime_Type::kLevel5Bp] = bp_timings[5];
743  start_end_times[beliefprop::Runtime_Type::kLevel5Copy] = data_copy_timings[5];
744  }
745  if (bp_timings.size() > 6) {
746  start_end_times[beliefprop::Runtime_Type::kLevel6DataCosts] = data_costs_timings[6];
747  start_end_times[beliefprop::Runtime_Type::kLevel6Bp] = bp_timings[6];
748  start_end_times[beliefprop::Runtime_Type::kLevel6Copy] = data_copy_timings[6];
749  }
750  if (bp_timings.size() > 7) {
751  start_end_times[beliefprop::Runtime_Type::kLevel7DataCosts] = data_costs_timings[7];
752  start_end_times[beliefprop::Runtime_Type::kLevel7Bp] = bp_timings[7];
753  start_end_times[beliefprop::Runtime_Type::kLevel7Copy] = data_copy_timings[7];
754  }
755  if (bp_timings.size() > 8) {
756  start_end_times[beliefprop::Runtime_Type::kLevel8DataCosts] = data_costs_timings[8];
757  start_end_times[beliefprop::Runtime_Type::kLevel8Bp] = bp_timings[8];
758  start_end_times[beliefprop::Runtime_Type::kLevel8Copy] = data_copy_timings[8];
759  }
760  if (bp_timings.size() > 9) {
761  start_end_times[beliefprop::Runtime_Type::kLevel9DataCosts] = data_costs_timings[9];
762  start_end_times[beliefprop::Runtime_Type::kLevel9Bp] = bp_timings[9];
763  start_end_times[beliefprop::Runtime_Type::kLevel9Copy] = data_copy_timings[9];
764  }
765 
766  //add timing for each runtime segment to segment_timings object
767  DetailedTimings segment_timings(beliefprop::kTimingNames);
768  std::ranges::for_each(start_end_times,
769  [&segment_timings](const auto& current_runtime_name_timing) {
770  segment_timings.AddTiming(
771  current_runtime_name_timing.first,
772  current_runtime_name_timing.second[1] - current_runtime_name_timing.second[0]);
773  });
774 
775  segment_timings.AddTiming(beliefprop::Runtime_Type::kBpIters, total_time_bp_iters);
776  segment_timings.AddTiming(beliefprop::Runtime_Type::kCopyData, total_time_copy_data);
777  segment_timings.AddTiming(beliefprop::Runtime_Type::kCopyDataKernel, total_time_copy_data_kernel);
778 
779  //compute total runtime
780  const auto total_time =
785  total_time_bp_iters +
786  total_time_copy_data +
789  segment_timings.AddTiming(beliefprop::Runtime_Type::kTotalTimed, total_time);
790 
791  //return resulting disparity map and timings for each processing segment
792  return std::pair<float*, DetailedTimings<beliefprop::Runtime_Type>>{
793  result_disp_map_device,
794  segment_timings};
795 }
796 
797 #endif /* PROCESS_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 store and retrieve properties of a bp processing level.
File with namespace for enums, constants, structures, and functions specific to belief propagation pr...
Declares structure to store the belief propagation settings including the number of levels and iterat...
Constants for timing belief propagation implementation.
Declares class to store timings of one or more segments taken during the run(s) of an implementation ...
Declares class for memory management with functions defined for standard memory allocation using CPU ...
Declares child class of ParallelParams to store and process parallelization parameters to use in each...
std::chrono::time_point< std::chrono::system_clock > timingType
Alias for time point for start and end time for each timing segment.
Definition: ProcessBp.h:55
Contains namespace with enums and constants for implementation run evaluation.
Declares and defines structure that stores settings for current implementation run as well as functio...
Define constraints for data type in processing.
Class to store and retrieve properties of a bp processing level including a data type specified as a ...
Definition: BpLevel.h:60
Class to store timings of one or more segments taken during the run(s) of an implementation or across...
std::chrono::duration< double > MedianTiming(const T run_segment_index) const
Get median timing for a specified segment that may have been run multiple times.
void AddTiming(const T timing_segment, const std::chrono::duration< double > &segment_time)
Add timing by segment index.
Class for memory management with functions defined for standard memory allocation using CPU....
Abstract class for holding and processing parallelization parameters. Child class(es) specific to im...
Abstract class to run belief propagation on target device. Some of the class functions need to be ove...
Definition: ProcessBp.h:67
std::optional< std::pair< float *, DetailedTimings< beliefprop::Runtime_Type > > > operator()(const std::array< float *, 2 > &images_target_device, const beliefprop::BpSettings &alg_settings, const std::array< unsigned int, 2 > &width_height_images, T *allocated_mem_bp_processing, T *allocated_memory, const std::unique_ptr< MemoryManagement< T >> &mem_management_bp_run) const
Run belief propagation implementation with on a set of stereo images to generate a disparity map....
Definition: ProcessBp.h:410
ProcessBp(const ParallelParams &parallel_params)
Definition: ProcessBp.h:69
const ParallelParams & parallel_params_
Definition: ProcessBp.h:103
virtual run_eval::Status ErrorCheck(const char *file="", int line=0, bool abort=false) const
Definition: ProcessBp.h:73
void RetrieveOutputDisparity(const beliefprop::BpLevelProperties &current_bp_level, const T *data_cost_checkerboard_0, const T *data_cost_checkerboard_1, const T *message_u_prev_checkerboard_0, const T *message_d_prev_checkerboard_0, const T *message_l_prev_checkerboard_0, const T *message_r_prev_checkerboard_0, const T *message_u_prev_checkerboard_1, const T *message_d_prev_checkerboard_1, const T *message_l_prev_checkerboard_1, const T *message_r_prev_checkerboard_1, float *disparity_between_images_device, unsigned int bp_settings_disp_vals, const ParallelParams &opt_cpu_params)
constexpr bool kAllocateFreeBpMemoryOutsideRuns
Definition: BpRunUtils.h:115
std::array< T, kNumCheckerboardParts > DataCostsCheckerboards
Define alias for two-element array with data costs for each bp processing checkerboard....
const std::unordered_map< Runtime_Type, std::string_view > kTimingNames
Mapping of runtime segment enum to header describing timing of the segment.
constexpr bool kUseOptMemManagement
Definition: BpRunUtils.h:113
std::array< std::array< T, kNumMessageArrays >, kNumCheckerboardParts > CheckerboardMessages
Define alias for array with message costs for each bp processing checkerboard. Each checkerboard mes...
Status
Enum for status to indicate if error or no error.
Structure to store the belief propagation settings including the number of levels and iterations.
Definition: BpSettings.h:87
unsigned int num_disp_vals
Number of disparity values must be set for each stereo set.
Definition: BpSettings.h:101
unsigned int num_levels
Definition: BpSettings.h:89