Skip to content

Commit 6afb4b0

Browse files
Merge pull request #1506 from murraystevenson/oneTBB2021
oneTBB 2021 Compatibility
2 parents 4d215ea + 11b9348 commit 6afb4b0

File tree

8 files changed

+173
-245
lines changed

8 files changed

+173
-245
lines changed

Changes

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
10.7.x.x (relative to 10.7.0.0a1)
22
========
33

4+
Improvements
5+
------------
6+
7+
- TBB : Improved compatibility with oneTBB 2021.
8+
9+
Breaking Changes
10+
----------------
411

12+
- IECore : Removed `tbb_task_scheduler_init()` Python Context Manager. Use `tbb_global_control()` instead.
513

614
10.7.0.0a1 (relative to 10.6.2.1)
715
==========

include/IECoreScene/private/PrimitiveAlgoUtils.h

Lines changed: 80 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -170,124 +170,107 @@ struct FillVectorFromValue
170170
size_t m_len;
171171
};
172172

173-
/// template to dispatch only primvars which are supported by the SplitTask
173+
/// template to dispatch only primvars which are supported by splitPrimitive
174174
/// Numeric & string like arrays, which contain elements which can be added to a std::set
175175
template<typename T> struct IsDeletablePrimVar : boost::mpl::or_< IECore::TypeTraits::IsStringVectorTypedData<T>, IECore::TypeTraits::IsNumericVectorTypedData<T> > {};
176176

177177

178178
template<typename T, typename S, typename P>
179-
class SplitTask : public tbb::task
179+
void splitPrimitive( const std::vector<T> &segments, typename P::Ptr primitive, const S& splitter, const std::string &primvarName, std::vector<typename P::Ptr> &outputPrimitives, size_t offset, size_t depth, const IECore::Canceller *canceller, tbb::task_group_context &taskGroupContext )
180180
{
181-
private:
182-
typedef typename P::Ptr Ptr;
183-
public:
184-
SplitTask(const std::vector<T> &segments, typename P::Ptr primitive, const S& splitter, const std::string &primvarName, std::vector<Ptr> &outputPrimitives, size_t offset, size_t depth, const IECore::Canceller *canceller )
185-
: m_segments(segments), m_primitive(primitive), m_splitter(splitter), m_primvarName(primvarName), m_outputPrimitives( outputPrimitives ), m_offset(offset), m_depth(depth), m_canceller( canceller )
186-
{
187-
}
188-
189-
task *execute() override
190-
{
191-
192-
if ( numPrimitives ( m_primitive.get() ) == 0 && !m_segments.empty() )
193-
{
194-
m_outputPrimitives[m_offset] = m_primitive;
195-
return nullptr;
196-
}
197-
198-
if ( m_segments.size () == 0 )
199-
{
200-
return nullptr;
201-
}
202-
203-
size_t offset = m_segments.size() / 2;
204-
typename std::vector<T>::iterator mid = m_segments.begin() + offset;
205-
206-
IECoreScene::PrimitiveVariable segmentPrimVar = m_primitive->variables.find( m_primvarName )->second;
181+
using Ptr = typename P::Ptr;
207182

208-
std::vector<T> lowerSegments (m_segments.begin(), mid);
209-
std::vector<T> upperSegments (mid, m_segments.end());
210-
211-
std::set<T> lowerSegmentsSet ( m_segments.begin(), mid );
212-
std::set<T> upperSegmentsSet (mid, m_segments.end());
183+
if( numPrimitives( primitive.get() ) == 0 && !segments.empty() )
184+
{
185+
outputPrimitives[offset] = primitive;
186+
return;
187+
}
213188

214-
const auto &readable = IECore::runTimeCast<IECore::TypedData<std::vector<T> > >( segmentPrimVar.data )->readable();
189+
if( segments.size() == 0 )
190+
{
191+
return;
192+
}
215193

216-
IECore::BoolVectorDataPtr deletionArrayLower = new IECore::BoolVectorData();
217-
auto &writableLower = deletionArrayLower->writable();
194+
size_t midOffset = segments.size() / 2;
218195

219-
IECore::BoolVectorDataPtr deletionArrayUpper = new IECore::BoolVectorData();
220-
auto &writableUpper = deletionArrayUpper->writable();
196+
IECoreScene::PrimitiveVariable segmentPrimVar = primitive->variables.find( primvarName )->second;
221197

222-
size_t deleteCount = 0;
223-
if( segmentPrimVar.indices )
224-
{
225-
auto &readableIndices = segmentPrimVar.indices->readable();
226-
writableLower.resize( readableIndices.size() );
227-
writableUpper.resize( readableIndices.size() );
198+
std::vector<T> lowerSegments( segments.begin(), segments.begin() + midOffset );
199+
std::vector<T> upperSegments( segments.begin() + midOffset, segments.end() );
228200

229-
for( size_t i = 0; i < readableIndices.size(); ++i )
230-
{
231-
size_t index = readableIndices[i];
232-
writableLower[i] = lowerSegmentsSet.find( readable[index] ) == lowerSegmentsSet.end();
233-
writableUpper[i] = upperSegmentsSet.find( readable[index] ) == upperSegmentsSet.end();
234-
235-
deleteCount += ( writableLower[i] && !lowerSegments.empty() ) || ( writableUpper[i] && !upperSegments.empty() ) ? 1 : 0;
236-
}
237-
}
238-
else
239-
{
240-
writableLower.resize( readable.size() );
241-
writableUpper.resize( readable.size() );
242-
243-
for( size_t i = 0; i < readable.size(); ++i )
244-
{
245-
writableLower[i] = lowerSegmentsSet.find( readable[i] ) == lowerSegmentsSet.end();
246-
writableUpper[i] = upperSegmentsSet.find( readable[i] ) == upperSegmentsSet.end();
247-
deleteCount += ( writableLower[i] && !lowerSegments.empty() ) || ( writableUpper[i] && !upperSegments.empty() ) ? 1 : 0;
248-
}
249-
}
201+
std::set<T> lowerSegmentsSet( lowerSegments.begin(), lowerSegments.end() );
202+
std::set<T> upperSegmentsSet( upperSegments.begin(), upperSegments.end() );
250203

251-
if ( m_segments.size() == 1 && deleteCount == 0)
252-
{
253-
m_outputPrimitives[m_offset] = m_primitive;
254-
return nullptr;
255-
}
204+
const auto &readable = IECore::runTimeCast<IECore::TypedData<std::vector<T> > >( segmentPrimVar.data )->readable();
256205

257-
IECoreScene::PrimitiveVariable::Interpolation i = splitPrimvarInterpolation( m_primitive.get() );
206+
IECore::BoolVectorDataPtr deletionArrayLower = new IECore::BoolVectorData();
207+
auto &writableLower = deletionArrayLower->writable();
258208

259-
IECoreScene::PrimitiveVariable delPrimVarLower( i, deletionArrayLower );
260-
Ptr a = m_splitter( m_primitive.get(), delPrimVarLower, false, m_canceller ) ;
209+
IECore::BoolVectorDataPtr deletionArrayUpper = new IECore::BoolVectorData();
210+
auto &writableUpper = deletionArrayUpper->writable();
261211

262-
IECoreScene::PrimitiveVariable delPrimVarUpper( i, deletionArrayUpper);
263-
Ptr b = m_splitter( m_primitive.get(), delPrimVarUpper, false, m_canceller ) ;
212+
size_t deleteCount = 0;
213+
if( segmentPrimVar.indices )
214+
{
215+
auto &readableIndices = segmentPrimVar.indices->readable();
216+
writableLower.resize( readableIndices.size() );
217+
writableUpper.resize( readableIndices.size() );
264218

265-
size_t numSplits = 2;
219+
for( size_t i = 0; i < readableIndices.size(); ++i )
220+
{
221+
size_t index = readableIndices[i];
222+
writableLower[i] = lowerSegmentsSet.find( readable[index] ) == lowerSegmentsSet.end();
223+
writableUpper[i] = upperSegmentsSet.find( readable[index] ) == upperSegmentsSet.end();
266224

267-
set_ref_count( 1 + numSplits);
225+
deleteCount += ( writableLower[i] && !lowerSegments.empty() ) || ( writableUpper[i] && !upperSegments.empty() ) ? 1 : 0;
226+
}
227+
}
228+
else
229+
{
230+
writableLower.resize( readable.size() );
231+
writableUpper.resize( readable.size() );
268232

269-
SplitTask *tA = new( allocate_child() ) SplitTask( lowerSegments, a, m_splitter, m_primvarName, m_outputPrimitives, m_offset, m_depth + 1, m_canceller);
270-
spawn( *tA );
233+
for( size_t i = 0; i < readable.size(); ++i )
234+
{
235+
writableLower[i] = lowerSegmentsSet.find( readable[i] ) == lowerSegmentsSet.end();
236+
writableUpper[i] = upperSegmentsSet.find( readable[i] ) == upperSegmentsSet.end();
237+
deleteCount += ( writableLower[i] && !lowerSegments.empty() ) || ( writableUpper[i] && !upperSegments.empty() ) ? 1 : 0;
238+
}
239+
}
271240

272-
SplitTask *tB = new( allocate_child() ) SplitTask( upperSegments, b, m_splitter, m_primvarName, m_outputPrimitives, m_offset + offset, m_depth + 1, m_canceller );
273-
spawn( *tB );
241+
if( segments.size() == 1 && deleteCount == 0 )
242+
{
243+
outputPrimitives[offset] = primitive;
244+
return;
245+
}
274246

275-
wait_for_all();
247+
IECoreScene::PrimitiveVariable::Interpolation i = splitPrimvarInterpolation( primitive.get() );
276248

277-
return nullptr;
278-
}
249+
IECoreScene::PrimitiveVariable delPrimVarLower( i, deletionArrayLower );
250+
Ptr a = splitter( primitive.get(), delPrimVarLower, false, canceller );
279251

280-
private:
252+
IECoreScene::PrimitiveVariable delPrimVarUpper( i, deletionArrayUpper);
253+
Ptr b = splitter( primitive.get(), delPrimVarUpper, false, canceller );
281254

282-
std::vector<T> m_segments;
283-
typename P::Ptr m_primitive;
284-
const S &m_splitter;
285-
std::string m_primvarName;
286-
std::vector<Ptr> &m_outputPrimitives;
287-
size_t m_offset;
288-
size_t m_depth;
289-
const IECore::Canceller *m_canceller;
290-
};
255+
tbb::parallel_for(
256+
tbb::blocked_range<size_t>( 0, 2 ),
257+
[&]( const tbb::blocked_range<size_t> &r )
258+
{
259+
for( size_t i = r.begin(); i != r.end(); ++i )
260+
{
261+
if( i == 0 )
262+
{
263+
splitPrimitive<T, S, P>( lowerSegments, a, splitter, primvarName, outputPrimitives, offset, depth + 1, canceller, taskGroupContext );
264+
}
265+
else
266+
{
267+
splitPrimitive<T, S, P>( upperSegments, b, splitter, primvarName, outputPrimitives, offset + midOffset, depth + 1, canceller, taskGroupContext );
268+
}
269+
}
270+
},
271+
taskGroupContext
272+
);
273+
}
291274

292275
template<typename P, typename S>
293276
class TaskSegmenter
@@ -323,17 +306,17 @@ class TaskSegmenter
323306
ReturnType results( segmentsReadable.size() );
324307

325308
tbb::task_group_context taskGroupContext( tbb::task_group_context::isolated );
326-
SplitTask<T, S, P> *task = new( tbb::task::allocate_root( taskGroupContext ) ) SplitTask<T, S, P>(
309+
splitPrimitive<T, S, P>(
327310
segmentsReadable,
328311
const_cast<P *>(m_primitive),
329312
m_splitter,
330313
m_primVarName,
331314
results,
332315
0,
333316
0,
334-
m_canceller
317+
m_canceller,
318+
taskGroupContext
335319
);
336-
tbb::task::spawn_root_and_wait( *task );
337320

338321
return results;
339322

include/IECoreVDB/VDBObject.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ IECORE_PUSH_DEFAULT_VISIBILITY
5353
#include "Imath/ImathBox.h"
5454
IECORE_POP_DEFAULT_VISIBILITY
5555

56-
#include "tbb/recursive_mutex.h"
57-
5856
#include <unordered_map>
5957

6058
namespace IECoreVDB

src/IECore/IndexedIOAlgo.cpp

Lines changed: 42 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434

3535
#include "IECore/IndexedIOAlgo.h"
3636

37-
#include "tbb/task.h"
37+
#include "tbb/blocked_range.h"
38+
#include "tbb/parallel_for.h"
3839

3940
#include <atomic>
4041

@@ -227,59 +228,52 @@ void recursiveCopy( const IndexedIO *src, IndexedIO *dst )
227228
}
228229
}
229230

230-
//! Task for traversing all files in parallel. New tasks are spawned for each directory
231+
//! Traverse all files in parallel.
231232
template<template<typename, typename> class FileHandler, typename FileCallback>
232-
class FileTask : public tbb::task
233+
void parallelFileWalk( const IndexedIO *src, FileCallback &fileCallback, tbb::task_group_context &taskGroupContext )
233234
{
235+
IndexedIO::EntryIDList fileNames;
236+
src->entryIds( fileNames, IndexedIO::EntryType::File );
234237

235-
public :
236-
237-
FileTask( const IndexedIO *src, FileCallback &fileCallback )
238-
: m_src( src ), m_fileCallback( fileCallback )
239-
{
240-
}
241-
242-
~FileTask() override
243-
{
244-
}
245-
246-
task *execute() override
247-
{
248-
IndexedIO::EntryIDList fileNames;
249-
m_src->entryIds( fileNames, IndexedIO::EntryType::File );
250-
251-
for( const auto &fileName : fileNames )
252-
{
253-
handleFile<FileHandler, FileCallback>( m_src, nullptr, fileName, m_fileCallback );
254-
}
255-
256-
IndexedIO::EntryIDList directoryNames;
257-
m_src->entryIds( directoryNames, IndexedIO::EntryType::Directory );
238+
for( const auto &fileName : fileNames )
239+
{
240+
handleFile<FileHandler, FileCallback>( src, nullptr, fileName, fileCallback );
241+
}
258242

259-
set_ref_count( 1 + directoryNames.size() );
243+
IndexedIO::EntryIDList directoryNames;
244+
src->entryIds( directoryNames, IndexedIO::EntryType::Directory );
245+
if( directoryNames.empty() )
246+
{
247+
return;
248+
}
260249

261-
std::vector<ConstIndexedIOPtr> childDirectories;
262-
childDirectories.reserve(directoryNames.size());
263-
for( const auto &directoryName : directoryNames )
264-
{
265-
childDirectories.push_back( m_src->subdirectory( directoryName, IndexedIO::ThrowIfMissing ) );
266-
}
250+
std::vector<ConstIndexedIOPtr> childDirectories;
251+
childDirectories.reserve(directoryNames.size());
252+
for( const auto &directoryName : directoryNames )
253+
{
254+
childDirectories.push_back( src->subdirectory( directoryName, IndexedIO::ThrowIfMissing ) );
255+
}
267256

268-
for( const auto &childDirectory : childDirectories )
257+
if( childDirectories.size() == 1 )
258+
{
259+
// Serial execution
260+
parallelFileWalk<FileHandler, FileCallback>( childDirectories[0].get(), fileCallback, taskGroupContext );
261+
}
262+
else
263+
{
264+
tbb::parallel_for(
265+
tbb::blocked_range<size_t>( 0, childDirectories.size() ),
266+
[&]( const tbb::blocked_range<size_t> &r )
269267
{
270-
FileTask *t = new( allocate_child() ) FileTask( childDirectory.get() , m_fileCallback );
271-
spawn( *t );
272-
}
273-
274-
wait_for_all();
275-
276-
return nullptr;
277-
}
278-
279-
private :
280-
const IndexedIO *m_src;
281-
FileCallback &m_fileCallback;
282-
};
268+
for( size_t i = r.begin(); i != r.end(); ++i )
269+
{
270+
parallelFileWalk<FileHandler, FileCallback>( childDirectories[i].get(), fileCallback, taskGroupContext );
271+
}
272+
},
273+
taskGroupContext
274+
);
275+
}
276+
}
283277

284278
} // namespace
285279

@@ -303,8 +297,7 @@ FileStats<size_t> parallelReadAll( const IndexedIO *src )
303297
};
304298

305299
tbb::task_group_context taskGroupContext( tbb::task_group_context::isolated );
306-
FileTask<Reader, decltype( fileCallback )> *task = new( tbb::task::allocate_root( taskGroupContext ) ) FileTask<Reader, decltype( fileCallback )>( src, fileCallback );
307-
tbb::task::spawn_root_and_wait( *task );
300+
parallelFileWalk<Reader, decltype( fileCallback )>( src, fileCallback, taskGroupContext );
308301
return fileStats;
309302
}
310303

0 commit comments

Comments
 (0)