7#ifndef PXR_EXEC_VDF_SPECULATION_EXECUTOR_ENGINE_H
8#define PXR_EXEC_VDF_SPECULATION_EXECUTOR_ENGINE_H
24PXR_NAMESPACE_OPEN_SCOPE
37template <
typename DataManagerType>
51 const VdfSpeculationExecutorBase &speculationExecutor,
52 DataManagerType *dataManager) :
54 speculationExecutor, dataManager),
56 speculationExecutor.GetNonSpeculationParentExecutor())) {
65 const VdfRequest &computeRequest,
68 schedule, computeRequest, errorLogger,
80 const VdfRequest &computeRequest,
92 Base::ExecutionStageStart;
96 struct _OutputToExecute {
101 stage(_ExecutionStageStart),
103 inputsSpeculate(false)
116 bool inputsSpeculate;
122 bool _PushBackOutputForSpeculation(
123 std::vector< _OutputToExecute > *outputs,
130 void _ExecuteOutputForSpeculation(
137 void _WriteBackComputedOutput(
149template <
typename DataManagerType>
152 std::vector< _OutputToExecute > *outputs,
159 outputs->push_back(_OutputToExecute(outputId));
169template <
typename DataManagerType>
174 const VdfRequest &computeRequest,
181 Base::_GetDataManager()->Resize(*schedule.
GetNetwork());
186 TfBits executedNodes(numNodes);
189 TfBits speculatedNodes(numNodes);
195 VdfRequest::IndexedView requestView(computeRequest);
196 for (
size_t i = 0; i < requestView.GetSize(); ++i) {
208 if (Base::_GetExecutor().GetOutputValue(output, mask)) {
209 callback(*maskedOutput, i);
213 _ExecuteOutputForSpeculation(
214 state, output, &executedNodes, &speculatedNodes);
217 if (Base::_GetExecutor().HasBeenInterrupted()) {
224 callback(*maskedOutput, i);
229template <
typename DataManagerType>
237 TF_DEBUG(VDF_SEE_TRACE).Msg(
"{ SpeculationOutputExecuteBegin();\n");
243 std::vector< _OutputToExecute > outputsStack;
250 std::vector< bool > speculated;
254 _PushBackOutputForSpeculation(&outputsStack, output, schedule);
256 bool hasBeenInterrupted = Base::_GetExecutor().HasBeenInterrupted();
258 while (!outputsStack.empty() && !hasBeenInterrupted) {
263 typename Base::_ExecutionStage stage = outputsStack.back().stage;
264 const size_t outputIndex = outputsStack.size() - 1;
271 bool previousStageSpeculated =
false;
272 while (outputsStack.back().numPushed) {
273 outputsStack.back().numPushed--;
274 previousStageSpeculated |= speculated.back();
275 speculated.pop_back();
280 case Base::ExecutionStageStart:
283 .Msg(
"{ SpeculationBeginNode(%p, \"%s\");\n",
290 if (
static_cast<const VdfSpeculationExecutorBase &
>(
291 Base::_GetExecutor()).IsSpeculatingNode(&node)) {
292 speculated.push_back(
true);
293 outputsStack.pop_back();
296 .Msg(
"SpeculationEndNodeSpeculationNode(); (cycle) }\n");
305 if (executedNodes->
IsSet(scheduleNodeIndex)) {
306 speculated.push_back(
307 speculatedNodes->
IsSet(scheduleNodeIndex));
308 outputsStack.pop_back();
311 .Msg(
"SpeculationEndNodeRedundantCompute(); }\n");
318 if (Base::_GetExecutor().GetOutputValue(
321 speculated.push_back(
false);
322 outputsStack.pop_back();
325 .Msg(
"SpeculationEndNodeFoundCache(); }\n");
334 outputsStack.back().stage = Base::ExecutionStagePreRequisitesDone;
339 if (input.input->GetSpec().IsPrerequisite()) {
340 const bool pushed = _PushBackOutputForSpeculation(
341 &outputsStack, *input.source, schedule);
342 outputsStack[outputIndex].numPushed += pushed;
349 if (outputsStack[outputIndex].numPushed > 0) {
354 case Base::ExecutionStagePreRequisitesDone:
361 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
368 outputsStack.back().stage = Base::ExecutionStageReadsDone;
372 if (affective && !previousStageSpeculated) {
387 const bool pushed = _PushBackOutputForSpeculation(
388 &outputsStack, *input.source, schedule);
389 outputsStack[outputIndex].numPushed += pushed;
397 if (outputsStack[outputIndex].numPushed > 0) {
401 case Base::ExecutionStageReadsDone:
404 outputsStack.back().stage = Base::ExecutionStageCompute;
407 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
412 input.input->GetAssociatedOutput();
423 const bool pushed = _PushBackOutputForSpeculation(
424 &outputsStack, *fromBufferOutput, schedule);
425 outputsStack[outputIndex].numPushed += pushed;
433 const bool pushed = _PushBackOutputForSpeculation(
434 &outputsStack, *input.source, schedule);
435 outputsStack[outputIndex].numPushed += pushed;
440 if (outputsStack[outputIndex].numPushed > 0) {
449 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
452 executedNodes->
Set(scheduleNodeIndex);
456 if (outputsStack.back().inputsSpeculate) {
459 .Msg(
"SpeculationSkipNode (cycle) (\"%s\"); }\n",
463 speculatedNodes->
Set(scheduleNodeIndex);
464 speculated.push_back(
true);
468 }
else if (affective) {
471 Base::_ComputeNode(state, node);
472 speculated.push_back(
false);
475 .Msg(
"SpeculationComputedNode(\"%s\"); }\n",
487 .Msg(
"SpeculationPassThrough(\"%s\"); }\n",
490 Base::_PassThroughNode(schedule, node);
491 speculated.push_back(
false);
496 hasBeenInterrupted = Base::_GetExecutor().HasBeenInterrupted();
510 VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
512 if (_writeBackExecutor &&
513 !hasBeenInterrupted &&
514 !outputsStack.back().inputsSpeculate) {
515 _WriteBackComputedOutput(output, outputId, schedule);
517 Base::_GetExecutor()._TouchOutput(output);
520 outputsStack.pop_back();
524 TF_DEBUG(VDF_SEE_TRACE).Msg(
"SpeculationOutputExecuteEnd(); }\n");
527template <
typename DataManagerType>
535 const typename Base::_DataHandle dataHandle =
536 Base::_GetDataManager()->GetDataHandle(output.
GetId());
537 if (!Base::_GetDataManager()->IsValidDataHandle(dataHandle)) {
543 Base::_GetDataManager()->GetBufferData(dataHandle);
567 _writeBackExecutor->SetOutputValue(output, *value, computedMask);
594 const VdfMask *writeBackMask = &computedMask;
597 !_writeBackExecutor->HasInvalidationTimestampMismatch(
598 output, *passToOutput)) {
602 if (!writeBackMask->
IsEmpty()) {
603 _writeBackExecutor->SetOutputValue(output, *value, *writeBackMask);
608PXR_NAMESPACE_CLOSE_SCOPE
Fast bit array that keeps track of the number of bits set and can find the next set in a timely manne...
void Set(size_t index)
Sets bit # index to one.
bool IsSet(size_t index) const
Returns true, if bit # index is set.
A context is the parameter bundle passed to callbacks of computations.
This object holds state that remains persistent during one round of network evaluation.
const VdfSchedule & GetSchedule() const
The schedule used for evaluation.
This object is responsible for storing the executor buffer data, comprised of the executor cache vect...
void ResetExecutorCache(const VdfMask &mask)
Reset the executor cache without releasing any memory and set the executor cache mask to mask.
const VdfMask & GetExecutorCacheMask() const
Get the available mask.
VdfVector * GetExecutorCache() const
Returns the executor cache stored at this buffer data instance.
A client may instantiate an object of this class and set it in an executor, to collect errors that ma...
Abstract base class for classes that execute a VdfNetwork to compute a requested set of values.
A VdfMask is placed on connections to specify the data flowing through them.
bool IsAllZeros() const
Returns true if this mask has all entries unset.
bool IsEmpty() const
Returns true if this mask is empty, i.e.
Class to hold on to an externally owned output and a mask.
VdfOutput * GetOutput() const
Returns the VdfOutput.
const VdfMask & GetMask() const
Returns the VdfMask.
This is the base class for all nodes in a VdfNetwork.
VDF_API const std::string GetDebugName() const
Returns the debug name for this node, if one is registered.
virtual VDF_API VdfRequiredInputsPredicate GetRequiredInputsPredicate(const VdfContext &context) const
Returns a predicate, determining whether a given input and its connections are required in order to f...
A VdfOutput represents an output on a node.
VdfId GetId() const
The unique id of this output.
const VdfInput * GetAssociatedInput() const
Returns the in/out connector associated with this output.
This class is a collection of common functions used by pulled based executors.
_ExecutionStage
This enum describes the stages that a node goes through in execution.
An OutputId is a small key object that, once obtained for a particular VdfOutput, can be used to quer...
bool IsValid() const
Returns whether this OutputId can be used to make queries about an output's scheduling.
Contains a specification of how to execute a particular VdfNetwork.
const VdfNetwork * GetNetwork() const
Returns the network for this schedule.
VDF_API OutputId GetOutputId(const VdfOutput &output) const
Returns a small, cheap OutputId, which can be passed to other Get* methods in this class to efficient...
VDF_API const VdfMask & GetRequestMask(const OutputId &outputId) const
Returns the request mask associated with the given OutputId.
VDF_API const VdfOutput * GetFromBufferOutput(const OutputId &outputId) const
Returns the "from buffer's" output associated with the given OutputId.
VDF_API InputsRange GetInputs(const VdfNode &node) const
Returns a range of inputs scheduled for the given node.
int GetScheduleNodeIndex(const OutputId &outputId) const
Returns the node index of the schedule node associated with the given outputId.
VDF_API const VdfMask & GetKeepMask(const OutputId &outputId) const
Returns the keep mask associated with the given OutputId.
VDF_API const VdfOutput * GetPassToOutput(const OutputId &outputId) const
Returns the "pass to" output associated with the given OutputId.
VDF_API const VdfNode * GetNode(const OutputId &outputId) const
Returns the VdfNode that owns the VdfOutput associated with the given outputId.
ScheduleNodeVector & GetScheduleNodeVector()
Returns the vector of schedule nodes in this schedule.
VDF_API bool IsAffective(const OutputId &outputId) const
Returns true if the output is expected to have an effect on its corresponding input,...
VDF_API const VdfOutput * GetOutput(const OutputId &outputId) const
Returns the scheduled VdfOutput associated with the given OutputId.
This class provides an executor engine to the speculation executor.
VdfSpeculationExecutorEngine(const VdfSpeculationExecutorBase &speculationExecutor, DataManagerType *dataManager)
Constructs an engine used by the speculation executor.
void RunSchedule(const VdfSchedule &schedule, const VdfRequest &computeRequest, VdfExecutorErrorLogger *errorLogger)
Executes the given schedule with a computeRequest and an optional /p errorLogger.
This class is used to abstract away knowledge of the cache data used for each node.
#define TF_DEBUG(enumVal)
Evaluate and print debugging message msg if enumVal is enabled for debugging.
#define TF_DEV_AXIOM(cond)
The same as TF_AXIOM, but compiled only in dev builds.
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.