Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
10.7.x.x (relative to 10.7.0.0a1)
========

Improvements
------------

- TBB : Improved compatibility with oneTBB 2021.

Breaking Changes
----------------

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

10.7.0.0a1 (relative to 10.6.2.1)
==========
Expand Down
177 changes: 80 additions & 97 deletions include/IECoreScene/private/PrimitiveAlgoUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,124 +170,107 @@ struct FillVectorFromValue
size_t m_len;
};

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


template<typename T, typename S, typename P>
class SplitTask : public tbb::task
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 )
{
private:
typedef typename P::Ptr Ptr;
public:
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 )
: m_segments(segments), m_primitive(primitive), m_splitter(splitter), m_primvarName(primvarName), m_outputPrimitives( outputPrimitives ), m_offset(offset), m_depth(depth), m_canceller( canceller )
{
}

task *execute() override
{

if ( numPrimitives ( m_primitive.get() ) == 0 && !m_segments.empty() )
{
m_outputPrimitives[m_offset] = m_primitive;
return nullptr;
}

if ( m_segments.size () == 0 )
{
return nullptr;
}

size_t offset = m_segments.size() / 2;
typename std::vector<T>::iterator mid = m_segments.begin() + offset;

IECoreScene::PrimitiveVariable segmentPrimVar = m_primitive->variables.find( m_primvarName )->second;
using Ptr = typename P::Ptr;

std::vector<T> lowerSegments (m_segments.begin(), mid);
std::vector<T> upperSegments (mid, m_segments.end());

std::set<T> lowerSegmentsSet ( m_segments.begin(), mid );
std::set<T> upperSegmentsSet (mid, m_segments.end());
if( numPrimitives( primitive.get() ) == 0 && !segments.empty() )
{
outputPrimitives[offset] = primitive;
return;
}

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

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

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

size_t deleteCount = 0;
if( segmentPrimVar.indices )
{
auto &readableIndices = segmentPrimVar.indices->readable();
writableLower.resize( readableIndices.size() );
writableUpper.resize( readableIndices.size() );
std::vector<T> lowerSegments( segments.begin(), segments.begin() + midOffset );
std::vector<T> upperSegments( segments.begin() + midOffset, segments.end() );

for( size_t i = 0; i < readableIndices.size(); ++i )
{
size_t index = readableIndices[i];
writableLower[i] = lowerSegmentsSet.find( readable[index] ) == lowerSegmentsSet.end();
writableUpper[i] = upperSegmentsSet.find( readable[index] ) == upperSegmentsSet.end();

deleteCount += ( writableLower[i] && !lowerSegments.empty() ) || ( writableUpper[i] && !upperSegments.empty() ) ? 1 : 0;
}
}
else
{
writableLower.resize( readable.size() );
writableUpper.resize( readable.size() );

for( size_t i = 0; i < readable.size(); ++i )
{
writableLower[i] = lowerSegmentsSet.find( readable[i] ) == lowerSegmentsSet.end();
writableUpper[i] = upperSegmentsSet.find( readable[i] ) == upperSegmentsSet.end();
deleteCount += ( writableLower[i] && !lowerSegments.empty() ) || ( writableUpper[i] && !upperSegments.empty() ) ? 1 : 0;
}
}
std::set<T> lowerSegmentsSet( lowerSegments.begin(), lowerSegments.end() );
std::set<T> upperSegmentsSet( upperSegments.begin(), upperSegments.end() );

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

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

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

IECoreScene::PrimitiveVariable delPrimVarUpper( i, deletionArrayUpper);
Ptr b = m_splitter( m_primitive.get(), delPrimVarUpper, false, m_canceller ) ;
size_t deleteCount = 0;
if( segmentPrimVar.indices )
{
auto &readableIndices = segmentPrimVar.indices->readable();
writableLower.resize( readableIndices.size() );
writableUpper.resize( readableIndices.size() );

size_t numSplits = 2;
for( size_t i = 0; i < readableIndices.size(); ++i )
{
size_t index = readableIndices[i];
writableLower[i] = lowerSegmentsSet.find( readable[index] ) == lowerSegmentsSet.end();
writableUpper[i] = upperSegmentsSet.find( readable[index] ) == upperSegmentsSet.end();

set_ref_count( 1 + numSplits);
deleteCount += ( writableLower[i] && !lowerSegments.empty() ) || ( writableUpper[i] && !upperSegments.empty() ) ? 1 : 0;
}
}
else
{
writableLower.resize( readable.size() );
writableUpper.resize( readable.size() );

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

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

wait_for_all();
IECoreScene::PrimitiveVariable::Interpolation i = splitPrimvarInterpolation( primitive.get() );

return nullptr;
}
IECoreScene::PrimitiveVariable delPrimVarLower( i, deletionArrayLower );
Ptr a = splitter( primitive.get(), delPrimVarLower, false, canceller );

private:
IECoreScene::PrimitiveVariable delPrimVarUpper( i, deletionArrayUpper);
Ptr b = splitter( primitive.get(), delPrimVarUpper, false, canceller );

std::vector<T> m_segments;
typename P::Ptr m_primitive;
const S &m_splitter;
std::string m_primvarName;
std::vector<Ptr> &m_outputPrimitives;
size_t m_offset;
size_t m_depth;
const IECore::Canceller *m_canceller;
};
tbb::parallel_for(
tbb::blocked_range<size_t>( 0, 2 ),
[&]( const tbb::blocked_range<size_t> &r )
{
for( size_t i = r.begin(); i != r.end(); ++i )
{
if( i == 0 )
{
splitPrimitive<T, S, P>( lowerSegments, a, splitter, primvarName, outputPrimitives, offset, depth + 1, canceller, taskGroupContext );
}
else
{
splitPrimitive<T, S, P>( upperSegments, b, splitter, primvarName, outputPrimitives, offset + midOffset, depth + 1, canceller, taskGroupContext );
}
}
},
taskGroupContext
);
}

template<typename P, typename S>
class TaskSegmenter
Expand Down Expand Up @@ -323,17 +306,17 @@ class TaskSegmenter
ReturnType results( segmentsReadable.size() );

tbb::task_group_context taskGroupContext( tbb::task_group_context::isolated );
SplitTask<T, S, P> *task = new( tbb::task::allocate_root( taskGroupContext ) ) SplitTask<T, S, P>(
splitPrimitive<T, S, P>(
segmentsReadable,
const_cast<P *>(m_primitive),
m_splitter,
m_primVarName,
results,
0,
0,
m_canceller
m_canceller,
taskGroupContext
);
tbb::task::spawn_root_and_wait( *task );

return results;

Expand Down
2 changes: 0 additions & 2 deletions include/IECoreVDB/VDBObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ IECORE_PUSH_DEFAULT_VISIBILITY
#include "Imath/ImathBox.h"
IECORE_POP_DEFAULT_VISIBILITY

#include "tbb/recursive_mutex.h"

#include <unordered_map>

namespace IECoreVDB
Expand Down
91 changes: 42 additions & 49 deletions src/IECore/IndexedIOAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@

#include "IECore/IndexedIOAlgo.h"

#include "tbb/task.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_for.h"

#include <atomic>

Expand Down Expand Up @@ -227,59 +228,52 @@ void recursiveCopy( const IndexedIO *src, IndexedIO *dst )
}
}

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

public :

FileTask( const IndexedIO *src, FileCallback &fileCallback )
: m_src( src ), m_fileCallback( fileCallback )
{
}

~FileTask() override
{
}

task *execute() override
{
IndexedIO::EntryIDList fileNames;
m_src->entryIds( fileNames, IndexedIO::EntryType::File );

for( const auto &fileName : fileNames )
{
handleFile<FileHandler, FileCallback>( m_src, nullptr, fileName, m_fileCallback );
}

IndexedIO::EntryIDList directoryNames;
m_src->entryIds( directoryNames, IndexedIO::EntryType::Directory );
for( const auto &fileName : fileNames )
{
handleFile<FileHandler, FileCallback>( src, nullptr, fileName, fileCallback );
}

set_ref_count( 1 + directoryNames.size() );
IndexedIO::EntryIDList directoryNames;
src->entryIds( directoryNames, IndexedIO::EntryType::Directory );
if( directoryNames.empty() )
{
return;
}

std::vector<ConstIndexedIOPtr> childDirectories;
childDirectories.reserve(directoryNames.size());
for( const auto &directoryName : directoryNames )
{
childDirectories.push_back( m_src->subdirectory( directoryName, IndexedIO::ThrowIfMissing ) );
}
std::vector<ConstIndexedIOPtr> childDirectories;
childDirectories.reserve(directoryNames.size());
for( const auto &directoryName : directoryNames )
{
childDirectories.push_back( src->subdirectory( directoryName, IndexedIO::ThrowIfMissing ) );
}

for( const auto &childDirectory : childDirectories )
if( childDirectories.size() == 1 )
{
// Serial execution
parallelFileWalk<FileHandler, FileCallback>( childDirectories[0].get(), fileCallback, taskGroupContext );
}
else
{
tbb::parallel_for(
tbb::blocked_range<size_t>( 0, childDirectories.size() ),
[&]( const tbb::blocked_range<size_t> &r )
{
FileTask *t = new( allocate_child() ) FileTask( childDirectory.get() , m_fileCallback );
spawn( *t );
}

wait_for_all();

return nullptr;
}

private :
const IndexedIO *m_src;
FileCallback &m_fileCallback;
};
for( size_t i = r.begin(); i != r.end(); ++i )
{
parallelFileWalk<FileHandler, FileCallback>( childDirectories[i].get(), fileCallback, taskGroupContext );
}
},
taskGroupContext
);
}
}

} // namespace

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

tbb::task_group_context taskGroupContext( tbb::task_group_context::isolated );
FileTask<Reader, decltype( fileCallback )> *task = new( tbb::task::allocate_root( taskGroupContext ) ) FileTask<Reader, decltype( fileCallback )>( src, fileCallback );
tbb::task::spawn_root_and_wait( *task );
parallelFileWalk<Reader, decltype( fileCallback )>( src, fileCallback, taskGroupContext );
return fileStats;
}

Expand Down
Loading