Loading...
Searching...
No Matches
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
11#include "pxr/pxr.h"
12#include "pxr/base/work/api.h"
14#include "pxr/base/work/impl.h"
16
17#include <algorithm>
18
19PXR_NAMESPACE_OPEN_SCOPE
20
33template<typename Fn>
34void
35WorkSerialForN(size_t n, Fn &&fn)
36{
37 std::forward<Fn>(fn)(0, n);
38}
39
55template <typename Fn>
56void
57WorkParallelForN(size_t n, Fn &&callback, size_t grainSize)
58{
59 if (n == 0)
60 return;
61
62 // Don't bother with parallel_for, if concurrency is limited to 1.
63 if (WorkHasConcurrency()) {
64 PXR_WORK_IMPL_NAMESPACE_USING_DIRECTIVE;
65 WorkImpl_ParallelForN(n, std::forward<Fn>(callback), grainSize);
66 } else {
67 // If concurrency is limited to 1, execute serially.
68 WorkSerialForN(n, std::forward<Fn>(callback));
69 }
70}
71
83template <typename Fn>
84void
85WorkParallelForN(size_t n, Fn &&callback)
86{
87 WorkParallelForN(n, std::forward<Fn>(callback), 1);
88}
89
103template <typename RangeType, typename Fn>
104void
105WorkParallelForTBBRange(const RangeType &range, Fn &&callback)
106{
107 // Don't bother with parallel_for, if concurrency is limited to 1.
108 if (WorkHasConcurrency()) {
109 PXR_WORK_IMPL_NAMESPACE_USING_DIRECTIVE;
110 // Use the work backend's ParallelForTBBRange if one exists
111 // otherwise use the default implementation below that builds off of the
112 // dispatcher.
113#if defined WORK_IMPL_HAS_PARALLEL_FOR_TBB_RANGE
114 WorkImpl_ParallelForTBBRange(range, std::forward<Fn>(callback));
115#else
116 // The parallel task responsible for recursively sub-dividing the range
117 // and invoking the callback on the sub-ranges.
118 class _RangeTask
119 {
120 public:
121 _RangeTask(
122 WorkDispatcher &dispatcher,
123 RangeType &&range,
124 const Fn &callback)
125 : _dispatcher(dispatcher)
126 , _range(std::move(range))
127 , _callback(callback) {}
128
129 void operator()() const {
130 // Subdivide the given range until it is no longer divisible, and
131 // recursively spawn _RangeTasks for the right side of the split.
132 RangeType &leftRange = _range;
133 while (leftRange.is_divisible()) {
134 RangeType rightRange(leftRange, tbb::split());
135 _dispatcher.Run(_RangeTask(
136 _dispatcher, std::move(rightRange), _callback));
137 }
138
139 // If there are any more entries remaining in the left-most side
140 // of the given range, invoke the callback on the left-most range.
141 if (!leftRange.empty()) {
142 std::invoke(_callback, leftRange);
143 }
144 }
145
146 private:
147 WorkDispatcher &_dispatcher;
148 mutable RangeType _range;
149 const Fn &_callback;
150 };
151
152 WorkDispatcher dispatcher;
153 RangeType range = range;
154 dispatcher.Run(_RangeTask(
155 dispatcher, range, std::forward<Fn>(callback)));
156#endif
157 } else {
158 // If concurrency is limited to 1, execute serially.
159 std::forward<Fn>(callback)(range);
160 }
161}
162
175template <typename InputIterator, typename Fn>
176inline void
178 InputIterator first, InputIterator last, Fn &&fn)
179{
180 if (WorkHasConcurrency()) {
181 PXR_WORK_IMPL_NAMESPACE_USING_DIRECTIVE;
182 WorkImpl_ParallelForEach(first, last, std::forward<Fn>(fn));
183 } else {
184 std::for_each(first, last, std::forward<Fn>(fn));
185 }
186}
187
188PXR_NAMESPACE_CLOSE_SCOPE
189
190#endif // PXR_BASE_WORK_LOOPS_H
A work dispatcher runs concurrent tasks.
Definition: dispatcher.h:176
void WorkParallelForTBBRange(const RangeType &range, Fn &&callback)
WorkParallelForTBBRange(const RangeType &r, Fn &&callback)
Definition: loops.h:105
void WorkParallelForEach(InputIterator first, InputIterator last, Fn &&fn)
WorkParallelForEach(Iterator first, Iterator last, CallbackType callback)
Definition: loops.h:177
void WorkParallelForN(size_t n, Fn &&callback, size_t grainSize)
WorkParallelForN(size_t n, CallbackType callback, size_t grainSize = 1)
Definition: loops.h:57
void WorkSerialForN(size_t n, Fn &&fn)
WorkSerialForN(size_t n, CallbackType callback)
Definition: loops.h:35
WORK_API bool WorkHasConcurrency()
Return true if WorkGetPhysicalConcurrencyLimit() returns a number greater than 1 and PXR_WORK_THREAD_...