DGtal 1.4.0
Loading...
Searching...
No Matches
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]
 
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]
 
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}
Domain domain

References 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
PointVector< dim, Integer > Point
Points in DGtal::SpaceND.
Definition SpaceND.h:110
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

References calc_image_checksum(), domain, 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().