OpenVDB 12.1.0

Loading...
Searching...
No Matches
ForEach.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5 \file nanovdb/util/ForEach.h
6
7 \author Ken Museth
8
9 \date August 24, 2020
10
11 \brief A unified wrapper for tbb::parallel_for and a naive std::thread fallback
12*/
13
14#ifndef NANOVDB_UTIL_FOREACH_H_HAS_BEEN_INCLUDED
15#define NANOVDB_UTIL_FOREACH_H_HAS_BEEN_INCLUDED
16
17#include <nanovdb/util/Range.h>// for Range1D
18
19#ifdef NANOVDB_USE_TBB
20#include <tbb/parallel_for.h>
21#else
22#include <thread>
23#include <mutex>
24#include <vector>
25#endif
26
27 namespace nanovdb {
28
29 namespace util {
30
31/// @brief simple wrapper for tbb::parallel_for with a naive std fallback
32///
33/// @param range Range, CoordBBox, tbb::blocked_range, blocked_range2D, or blocked_range3D.
34/// @param func functor with the signature [](const RangeT&){...},
35///
36/// @code
37/// std::vector<int> array(100);
38/// auto func = [&array](auto &r){for (auto i=r.begin(); i!=r.end(); ++i) array[i]=i;};
39/// forEach(array, func);
40/// @endcode
41 template <typename RangeT, typename FuncT>
42 inline void forEach(RangeT range, const FuncT &func)
43{
44 if (range.empty()) return;
45#ifdef NANOVDB_USE_TBB
46 tbb::parallel_for(range, func);
47#else// naive and likely slow alternative based on std::thread
48 if (const size_t threadCount = std::thread::hardware_concurrency()>>1) {
49 std::vector<RangeT> rangePool{ range };
50 while(rangePool.size() < threadCount) {
51 const size_t oldSize = rangePool.size();
52 for (size_t i = 0; i < oldSize && rangePool.size() < threadCount; ++i) {
53 auto &r = rangePool[i];
54 if (r.is_divisible()) rangePool.push_back(RangeT(r, Split()));
55 }
56 if (rangePool.size() == oldSize) break;// none of the ranges were divided so stop
57 }
58 std::vector<std::thread> threadPool;
59 for (auto &r : rangePool) threadPool.emplace_back(func, r);// launch threads
60 for (auto &t : threadPool) t.join();// synchronize threads
61 } else {//serial
62 func(range);
63 }
64#endif
65}
66
67/// @brief Simple wrapper for the function defined above
68 template <typename FuncT>
69 inline void forEach(size_t begin, size_t end, size_t grainSize, const FuncT& func)
70{
71 forEach(Range1D(begin, end, grainSize), func);
72}
73
74/// @brief Simple wrapper for the function defined above, which works with std::containers
75 template <template<typename...> class ContainerT, typename... T, typename FuncT>
76 inline void forEach(const ContainerT<T...> &c, const FuncT& func)
77{
78 forEach(Range1D(0, c.size(), 1), func);
79}
80
81/// @brief Simple wrapper for the function defined above, which works with std::containers
82 template <template<typename...> class ContainerT, typename... T, typename FuncT>
83 inline void forEach(const ContainerT<T...> &c, size_t grainSize, const FuncT& func)
84{
85 forEach(Range1D(0, c.size(), grainSize), func);
86}
87
88}// namespace util
89
90/// @brief Simple wrapper for the function defined above
91 template <typename FuncT>
92[[deprecated("Use nanovdb::util::forEach instead")]]
93 inline void forEach(size_t begin, size_t end, size_t grainSize, const FuncT& func)
94{
95 util::forEach(util::Range1D(begin, end, grainSize), func);
96}
97
98/// @brief Simple wrapper for the function defined above, which works with std::containers
99 template <template<typename...> class ContainerT, typename... T, typename FuncT>
100[[deprecated("Use nanovdb::util::forEach instead")]]
101 inline void forEach(const ContainerT<T...> &c, const FuncT& func)
102{
103 util::forEach(util::Range1D(0, c.size(), 1), func);
104}
105
106/// @brief Simple wrapper for the function defined above, which works with std::containers
107 template <template<typename...> class ContainerT, typename... T, typename FuncT>
108[[deprecated("Use nanovdb::util::forEach instead")]]
109 inline void forEach(const ContainerT<T...> &c, size_t grainSize, const FuncT& func)
110{
111 util::forEach(util::Range1D(0, c.size(), grainSize), func);
112}
113
114}// namespace nanovdb
115
116#endif // NANOVDB_UTIL_FOREACH_H_HAS_BEEN_INCLUDED
Range.h
Custom Range class that is compatible with the tbb::blocked_range classes.
nanovdb::util::Split
Definition Range.h:28
nanovdb::util
Definition ForEach.h:29
nanovdb::util::forEach
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition ForEach.h:42
nanovdb::util::Range1D
Range< 1, size_t > Range1D
Definition Range.h:33
nanovdb
Definition GridHandle.h:27
nanovdb::forEach
void forEach(size_t begin, size_t end, size_t grainSize, const FuncT &func)
Simple wrapper for the function defined above.
Definition ForEach.h:93