OpenVDB  12.0.0
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
Definition: Range.h:28
Definition: GridHandle.h:27
Range< 1, size_t > Range1D
Definition: Range.h:33
Custom Range class that is compatible with the tbb::blocked_range classes.
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition: ForEach.h:42
Definition: Range.h:31