HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
loops.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_WORK_LOOPS_H
8 #define PXR_BASE_WORK_LOOPS_H
9 
10 /// \file work/loops.h
11 #include "pxr/pxr.h"
13 #include "pxr/base/work/api.h"
14 
15 #include <tbb/blocked_range.h>
16 #include <tbb/parallel_for.h>
17 #include <tbb/parallel_for_each.h>
18 #include <tbb/task_group.h>
19 
21 
22 ///////////////////////////////////////////////////////////////////////////////
23 ///
24 /// WorkSerialForN(size_t n, CallbackType callback)
25 ///
26 /// A serial version of WorkParallelForN as a drop in replacement to
27 /// selectively turn off multithreading for a single parallel loop for easier
28 /// debugging.
29 ///
30 /// Callback must be of the form:
31 ///
32 /// void LoopCallback(size_t begin, size_t end);
33 ///
34 template<typename Fn>
35 void
36 WorkSerialForN(size_t n, Fn &&fn)
37 {
38  std::forward<Fn>(fn)(0, n);
39 }
40 
41 ///////////////////////////////////////////////////////////////////////////////
42 ///
43 /// WorkParallelForN(size_t n, CallbackType callback, size_t grainSize = 1)
44 ///
45 /// Runs \p callback in parallel over the range 0 to n.
46 ///
47 /// Callback must be of the form:
48 ///
49 /// void LoopCallback(size_t begin, size_t end);
50 ///
51 /// grainSize specifies a minimum amount of work to be done per-thread. There
52 /// is overhead to launching a thread (or task) and a typical guideline is that
53 /// you want to have at least 10,000 instructions to count for the overhead of
54 /// launching a thread.
55 ///
56 template <typename Fn>
57 void
58 WorkParallelForN(size_t n, Fn &&callback, size_t grainSize)
59 {
60  if (n == 0)
61  return;
62 
63  // Don't bother with parallel_for, if concurrency is limited to 1.
64  if (WorkHasConcurrency()) {
65 
66  class Work_ParallelForN_TBB
67  {
68  public:
69  Work_ParallelForN_TBB(Fn &fn) : _fn(fn) { }
70 
71  void operator()(const tbb::blocked_range<size_t> &r) const {
72  // Note that we std::forward _fn using Fn in order get the
73  // right operator().
74  // We maintain the right type in this way:
75  // If Fn is T&, then reference collapsing gives us T& for _fn
76  // If Fn is T, then std::forward correctly gives us T&& for _fn
77  std::forward<Fn>(_fn)(r.begin(), r.end());
78  }
79 
80  private:
81  Fn &_fn;
82  };
83 
84  // In most cases we do not want to inherit cancellation state from the
85  // parent context, so we create an isolated task group context.
86  tbb::task_group_context ctx(tbb::task_group_context::isolated);
87  tbb::parallel_for(tbb::blocked_range<size_t>(0,n,grainSize),
88  Work_ParallelForN_TBB(callback),
89  ctx);
90 
91  } else {
92 
93  // If concurrency is limited to 1, execute serially.
94  WorkSerialForN(n, std::forward<Fn>(callback));
95 
96  }
97 }
98 
99 ///////////////////////////////////////////////////////////////////////////////
100 ///
101 /// WorkParallelForN(size_t n, CallbackType callback, size_t grainSize = 1)
102 ///
103 /// Runs \p callback in parallel over the range 0 to n.
104 ///
105 /// Callback must be of the form:
106 ///
107 /// void LoopCallback(size_t begin, size_t end);
108 ///
109 ///
110 template <typename Fn>
111 void
112 WorkParallelForN(size_t n, Fn &&callback)
113 {
114  WorkParallelForN(n, std::forward<Fn>(callback), 1);
115 }
116 
117 ///////////////////////////////////////////////////////////////////////////////
118 ///
119 /// WorkParallelForEach(Iterator first, Iterator last, CallbackType callback)
120 ///
121 /// Callback must be of the form:
122 ///
123 /// void LoopCallback(T elem);
124 ///
125 /// where the type T is deduced from the type of the InputIterator template
126 /// argument.
127 ///
128 ///
129 ///
130 template <typename InputIterator, typename Fn>
131 inline void
133  InputIterator first, InputIterator last, Fn &&fn)
134 {
135  tbb::task_group_context ctx(tbb::task_group_context::isolated);
136  tbb::parallel_for_each(first, last, std::forward<Fn>(fn), ctx);
137 }
138 
140 
141 #endif // PXR_BASE_WORK_LOOPS_H
GLint first
Definition: glcorearb.h:405
PXR_NAMESPACE_OPEN_SCOPE void WorkSerialForN(size_t n, Fn &&fn)
Definition: loops.h:36
void WorkParallelForN(size_t n, Fn &&callback, size_t grainSize)
Definition: loops.h:58
GLdouble n
Definition: glcorearb.h:2008
OIIO_UTIL_API void parallel_for(int32_t begin, int32_t end, function_view< void(int32_t)> task, paropt opt=0)
WORK_API bool WorkHasConcurrency()
void WorkParallelForEach(InputIterator first, InputIterator last, Fn &&fn)
Definition: loops.h:132
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
GLboolean r
Definition: glcorearb.h:1222