DGtal  1.4.2
exampleHyperRectDomainParallelScan.cpp File Reference

Example of parallelization of an HyperRectDomain scan and ImageContainerBySTL initialization. More...

#include <numeric>
#include <iterator>
#include <chrono>
#include <string>
#include <iostream>
#include <iomanip>
#include <omp.h>
#include "DGtal/base/Common.h"
#include "DGtal/kernel/SpaceND.h"
#include "DGtal/kernel/PointVector.h"
#include "DGtal/kernel/domains/HyperRectDomain.h"
#include "DGtal/images/ImageContainerBySTLVector.h"
#include "DGtal/base/SimpleConstRange.h"
Include dependency graph for exampleHyperRectDomainParallelScan.cpp:

Go to the source code of this file.

Functions

void tic ()
 
double toc ()
 
template<typename TIterator >
SimpleConstRange< TIterator > split_range (TIterator it_begin, TIterator it_end, std::size_t idx, std::size_t count)
 [split_range] More...
 
template<typename TIterable >
auto split_range (TIterable &iterable, std::size_t idx, std::size_t count) -> decltype(split_range(iterable.begin(), iterable.end(), idx, count))
 
template<typename Image >
Image::Value calc_image_checksum (Image const &image)
 [split_range] More...
 
template<typename Domain , typename Function >
auto sum_fn_on_domain (Domain const &domain, Function const &fn) -> decltype(fn(domain.lowerBound()))
 
template<typename Image , typename Function >
void init_image_getset (Image &image, Function const &fn)
 
template<typename Image , typename Function >
void init_image_iter (Image &image, Function const &fn)
 
int main (int argc, char *argv[])
 

Variables

auto tic_timer = std::chrono::high_resolution_clock::now()
 

Detailed Description

Example of parallelization of an HyperRectDomain scan and ImageContainerBySTL initialization.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Author
Roland Denis (denis.nosp@m.@mat.nosp@m.h.uni.nosp@m.v-ly.nosp@m.on1.f.nosp@m.r ) CNRS, Institut Camille Jordan (UMR 5208), Université Lyon 1, France
Date
2019/10/16

This file is part of the DGtal library.

Definition in file exampleHyperRectDomainParallelScan.cpp.

Function Documentation

◆ calc_image_checksum()

template<typename Image >
Image::Value calc_image_checksum ( Image const &  image)

[split_range]

Definition at line 93 of file exampleHyperRectDomainParallelScan.cpp.

94 {
95  typename Image::Value sum = 0;
96 
97  #pragma omp parallel reduction(+:sum)
98  {
99  std::size_t thread_idx = omp_get_thread_num();
100  std::size_t thread_cnt = omp_get_max_threads();
101  auto const range = split_range(image, thread_idx, thread_cnt);
102  sum = std::accumulate(range.begin(), range.end(), sum);
103  }
104 
105  return sum;
106 }
SimpleConstRange< TIterator > split_range(TIterator it_begin, TIterator it_end, std::size_t idx, std::size_t count)
[split_range]

References split_range().

Referenced by main().

◆ init_image_getset()

template<typename Image , typename Function >
void init_image_getset ( Image image,
Function const &  fn 
)

[image_init_getset]

[image_init_getset]

Definition at line 132 of file exampleHyperRectDomainParallelScan.cpp.

133 {
135  #pragma omp parallel
136  {
137  std::size_t thread_idx = omp_get_thread_num();
138  std::size_t thread_cnt = omp_get_num_threads();
139 
140  for (auto const& pt : split_range(image.domain(), thread_idx, thread_cnt))
141  image.setValue(pt, fn(pt, image(pt)));
142  }
144 }
Image image(domain)

References image(), and split_range().

Referenced by main().

◆ init_image_iter()

template<typename Image , typename Function >
void init_image_iter ( Image image,
Function const &  fn 
)

[image_init_iter]

[image_init_iter]

Definition at line 148 of file exampleHyperRectDomainParallelScan.cpp.

149 {
151  #pragma omp parallel
152  {
153  std::size_t thread_idx = omp_get_thread_num();
154  std::size_t thread_cnt = omp_get_num_threads();
155 
156  auto domain_it = split_range(image.domain(), thread_idx, thread_cnt).begin();
157  for (auto & v : split_range(image, thread_idx, thread_cnt))
158  {
159  v = fn(*domain_it, v);
160  ++domain_it;
161  }
162  }
164 }

References split_range().

Referenced by main().

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 166 of file exampleHyperRectDomainParallelScan.cpp.

167 {
168  using Space = SpaceND<3>;
169  using Point = Space::Point;
171  using Value = double;
173 
174  if (argc < 2)
175  {
176  std::cerr << "Usage: " << argv[0] << " <domain_size>" << std::endl;
177  return 1;
178  }
179 
180  trace.info() << "Initialization..." << std::endl;
181  std::size_t domain_size = std::stoll(argv[1]);
182  Domain domain(Point::diagonal(0), Point::diagonal(domain_size-1));
183  Image image(domain);
184 
185  double ref_duration = 0;
186  std::size_t max_threads = omp_get_max_threads();
187  trace.info() << std::fixed << std::setprecision(6);
188 
190  // Choose here the function you want to use
191 
192  //auto const fn = [&domain] (Point const& pt) { return 25 * ( std::cos( (pt - domain.upperBound()).norm() ) + 1 ); }; // CPU intensive
193  auto const fn = [&domain] (Point const& pt) { return (pt - domain.upperBound()).norm(); }; // Mixed
194  //auto const fn = [] (Point const& pt) { return Value(pt[0]); }; // Memory bound
195 
196 
198  // Scanning a domain in parallel
199 
200  trace.info() << std::endl;
201  trace.info() << "Scanning a domain in parallel..." << std::endl;
202  for (std::size_t thread_cnt = 1; thread_cnt <= max_threads; ++thread_cnt)
203  {
204  omp_set_num_threads(thread_cnt);
205  Value sum = sum_fn_on_domain(domain, fn);
206  tic();
207  sum += sum_fn_on_domain(domain, fn);
208  const double duration = toc();
209 
210  if (thread_cnt == 1)
211  ref_duration = duration;
212 
213  trace.info() << "\tthreads: " << thread_cnt
214  << "\tduration: " << duration << "s"
215  << "\tspeed: " << 1e-6 * domain.size() / duration << "Mpt/s"
216  << "\tspeedup: " << ref_duration/duration
217  << "\tchecksum: " << sum
218  << std::endl;
219  }
220 
221 
223  // Initializing an image in parallel using getter and setter
224 
225  trace.info() << std::endl;
226  trace.info() << "Initializing an image in parallel using getter and setter..." << std::endl;
227  for (std::size_t thread_cnt = 1; thread_cnt <= max_threads; ++thread_cnt)
228  {
229  omp_set_num_threads(thread_cnt);
230  init_image_getset(image, [&fn] (Point const& pt, Value) { return fn(pt); });
231  tic();
232  init_image_getset(image, [&fn] (Point const& pt, Value v) { return v + fn(pt); });
233  const double duration = toc();
234 
235  if (thread_cnt == 1)
236  ref_duration = duration;
237 
238  trace.info() << "\tthreads: " << thread_cnt
239  << "\tduration: " << duration << "s"
240  << "\tspeed: " << 1e-6 * domain.size() / duration << "Mpt/s"
241  << "\tspeedup: " << ref_duration/duration
242  << "\tchecksum: " << calc_image_checksum(image)
243  << std::endl;
244  }
245 
246 
248  // Initializing an image in parallel using iterators
249 
250  trace.info() << std::endl;
251  trace.info() << "Initializing an image in parallel using iterators..." << std::endl;
252  for (std::size_t thread_cnt = 1; thread_cnt <= max_threads; ++thread_cnt)
253  {
254  omp_set_num_threads(thread_cnt);
255  init_image_iter(image, [&fn] (Point const& pt, Value) { return fn(pt); });
256  tic();
257  init_image_iter(image, [&fn] (Point const& pt, Value v) { return v + fn(pt); });
258  const double duration = toc();
259 
260  if (thread_cnt == 1)
261  ref_duration = duration;
262 
263  trace.info() << "\tthreads: " << thread_cnt
264  << "\tduration: " << duration << "s"
265  << "\tspeed: " << 1e-6 * domain.size() / duration << "Mpt/s"
266  << "\tspeedup: " << ref_duration/duration
267  << "\tchecksum: " << calc_image_checksum(image)
268  << std::endl;
269  }
270 
271  return 0;
272 }
const Point & upperBound() const
Aim: implements association bewteen points lying in a digital domain and values.
Definition: Image.h:70
std::ostream & info()
Image::Value calc_image_checksum(Image const &image)
[split_range]
void init_image_iter(Image &image, Function const &fn)
void init_image_getset(Image &image, Function const &fn)
auto sum_fn_on_domain(Domain const &domain, Function const &fn) -> decltype(fn(domain.lowerBound()))
Trace trace
Definition: Common.h:153
MyPointD Point
Definition: testClone2.cpp:383
Domain domain

References calc_image_checksum(), domain, image(), DGtal::Trace::info(), init_image_getset(), init_image_iter(), DGtal::HyperRectDomain< TSpace >::size(), sum_fn_on_domain(), tic(), toc(), DGtal::trace, and DGtal::HyperRectDomain< TSpace >::upperBound().

◆ split_range() [1/2]

template<typename TIterable >
auto split_range ( TIterable &  iterable,
std::size_t  idx,
std::size_t  count 
) -> decltype(split_range(iterable.begin(), iterable.end(), idx, count))

Definition at line 84 of file exampleHyperRectDomainParallelScan.cpp.

86 {
87  return split_range(iterable.begin(), iterable.end(), idx, count);
88 }

References split_range().

◆ split_range() [2/2]

template<typename TIterator >
SimpleConstRange<TIterator> split_range ( TIterator  it_begin,
TIterator  it_end,
std::size_t  idx,
std::size_t  count 
)

[split_range]

Definition at line 73 of file exampleHyperRectDomainParallelScan.cpp.

74 {
75  auto range_size = std::distance(it_begin, it_end);
76  auto begin_shift = (range_size*idx) / count;
77  auto end_shift = (range_size*(idx+1)) / count;
78  return { it_begin + begin_shift, it_begin + end_shift };
79 }

Referenced by calc_image_checksum(), init_image_getset(), init_image_iter(), split_range(), and sum_fn_on_domain().

◆ sum_fn_on_domain()

template<typename Domain , typename Function >
auto sum_fn_on_domain ( Domain const &  domain,
Function const &  fn 
) -> decltype(fn(domain.lowerBound()))

[domain_scan]

[domain_scan]

Definition at line 110 of file exampleHyperRectDomainParallelScan.cpp.

112 {
114  auto sum = 0 * fn(domain.lowerBound()); // To initialize the sum depending on the function return type
115 
116  #pragma omp parallel reduction(+:sum)
117  {
118  // OpenMP context
119  std::size_t thread_idx = omp_get_thread_num();
120  std::size_t thread_cnt = omp_get_num_threads();
121 
122  for (auto const& pt : split_range(domain, thread_idx, thread_cnt))
123  sum += fn(pt);
124  }
126 
127  return sum;
128 }
const Point & lowerBound() const

References domain, DGtal::HyperRectDomain< TSpace >::lowerBound(), and split_range().

Referenced by main().

◆ tic()

void tic ( )

Definition at line 56 of file exampleHyperRectDomainParallelScan.cpp.

57 {
58  tic_timer = std::chrono::high_resolution_clock::now();
59 }

References tic_timer.

Referenced by main().

◆ toc()

double toc ( )

Definition at line 62 of file exampleHyperRectDomainParallelScan.cpp.

63 {
64  const auto toc_timer = std::chrono::high_resolution_clock::now();
65  const std::chrono::duration<double> time_span = toc_timer - tic_timer;
66  return time_span.count();
67 }

References tic_timer.

Referenced by main().

Variable Documentation

◆ tic_timer

auto tic_timer = std::chrono::high_resolution_clock::now()

Definition at line 53 of file exampleHyperRectDomainParallelScan.cpp.

Referenced by tic(), and toc().