Dispatcher::TaskBatch::TaskBatch( const ExecutableNode::Task &task ) : m_node( task.node() ), m_context( task.context() ), m_frames(), m_requirements() { m_blindData = new CompoundData; if ( task.hash() != MurmurHash() ) { m_frames.push_back( task.context()->getFrame() ); } }
IECore::MurmurHash Dispatcher::batchHash( const ExecutableNode::Task &task ) { MurmurHash result; result.append( (uint64_t)task.node() ); if ( task.hash() == MurmurHash() ) { return result; } const Context *context = task.context(); std::vector<IECore::InternedString> names; context->names( names ); for ( std::vector<IECore::InternedString>::const_iterator it = names.begin(); it != names.end(); ++it ) { // ignore the frame and the ui values if ( ( *it != g_frame ) && it->string().compare( 0, 3, "ui:" ) ) { result.append( *it ); if ( const IECore::Data *data = context->get<const IECore::Data>( *it ) ) { data->hash( result ); } } } return result; }
void Dispatcher::batchTasksWalk( Dispatcher::TaskBatchPtr parent, const ExecutableNode::Task &task, BatchMap ¤tBatches, TaskToBatchMap &tasksToBatches, std::set<const TaskBatch *> &ancestors ) { TaskBatchPtr batch = acquireBatch( task, currentBatches, tasksToBatches ); TaskBatches &parentRequirements = parent->requirements(); if ( std::find( parentRequirements.begin(), parentRequirements.end(), batch ) == parentRequirements.end() ) { if ( ancestors.find( batch.get() ) != ancestors.end() ) { throw IECore::Exception( ( boost::format( "Dispatched nodes cannot have cyclic dependencies. %s and %s are involved in a cycle." ) % batch->node()->relativeName( batch->node()->scriptNode() ) % parent->node()->relativeName( parent->node()->scriptNode() ) ).str() ); } parentRequirements.push_back( batch ); } ExecutableNode::Tasks taskRequirements; task.node()->requirements( task.context(), taskRequirements ); ancestors.insert( parent.get() ); for ( ExecutableNode::Tasks::const_iterator it = taskRequirements.begin(); it != taskRequirements.end(); ++it ) { batchTasksWalk( batch, *it, currentBatches, tasksToBatches, ancestors ); } ancestors.erase( parent.get() ); }
Dispatcher::TaskBatchPtr Dispatcher::acquireBatch( const ExecutableNode::Task &task, BatchMap ¤tBatches, TaskToBatchMap &tasksToBatches ) { MurmurHash taskHash = task.hash(); TaskToBatchMap::iterator it = tasksToBatches.find( taskHash ); if ( it != tasksToBatches.end() ) { return it->second; } MurmurHash hash = batchHash( task ); BatchMap::iterator bIt = currentBatches.find( hash ); if ( bIt != currentBatches.end() ) { TaskBatchPtr batch = bIt->second; std::vector<float> &frames = batch->frames(); const CompoundPlug *dispatcherPlug = task.node()->dispatcherPlug(); const IntPlug *batchSizePlug = dispatcherPlug->getChild<const IntPlug>( g_batchSize ); size_t batchSize = ( batchSizePlug ) ? batchSizePlug->getValue() : 1; if ( task.node()->requiresSequenceExecution() || ( frames.size() < batchSize ) ) { if ( task.hash() != MurmurHash() ) { float frame = task.context()->getFrame(); if ( std::find( frames.begin(), frames.end(), frame ) == frames.end() ) { if ( task.node()->requiresSequenceExecution() ) { frames.insert( std::lower_bound( frames.begin(), frames.end(), frame ), frame ); } else { frames.push_back( frame ); } } } if ( taskHash != MurmurHash() ) { tasksToBatches[taskHash] = batch; } return batch; } } TaskBatchPtr batch = new TaskBatch( task ); currentBatches[hash] = batch; if ( taskHash != MurmurHash() ) { tasksToBatches[taskHash] = batch; } return batch; }
static ContextPtr taskContext( const ExecutableNode::Task &t, bool copy = true ) { if ( ConstContextPtr context = t.context() ) { if ( copy ) { return new Context( *context ); } return boost::const_pointer_cast<Context>( context ); } return 0; }
void Dispatcher::batchTasksWalk( Dispatcher::TaskBatchPtr parent, const ExecutableNode::Task &task, BatchMap ¤tBatches, TaskToBatchMap &tasksToBatches ) { TaskBatchPtr batch = acquireBatch( task, currentBatches, tasksToBatches ); TaskBatches &parentRequirements = parent->requirements(); if ( ( batch != parent ) && std::find( parentRequirements.begin(), parentRequirements.end(), batch ) == parentRequirements.end() ) { parentRequirements.push_back( batch ); } ExecutableNode::Tasks taskRequirements; task.node()->requirements( task.context(), taskRequirements ); for ( ExecutableNode::Tasks::const_iterator it = taskRequirements.begin(); it != taskRequirements.end(); ++it ) { batchTasksWalk( batch, *it, currentBatches, tasksToBatches ); } }