7#ifndef PXR_EXEC_VDF_SPECULATION_EXECUTOR_ENGINE_H
8#define PXR_EXEC_VDF_SPECULATION_EXECUTOR_ENGINE_H
26PXR_NAMESPACE_OPEN_SCOPE
39template <
typename DataManagerType>
53 const VdfSpeculationExecutorBase &speculationExecutor,
54 DataManagerType *dataManager) :
56 speculationExecutor, dataManager),
58 speculationExecutor.GetNonSpeculationParentExecutor())) {
67 const VdfRequest &computeRequest,
70 schedule, computeRequest, errorLogger,
82 const VdfRequest &computeRequest,
94 Base::ExecutionStageStart;
98 struct _OutputToExecute {
103 stage(_ExecutionStageStart),
105 inputsSpeculate(false)
118 bool inputsSpeculate;
124 bool _PushBackOutputForSpeculation(
125 std::vector< _OutputToExecute > *outputs,
132 void _ExecuteOutputForSpeculation(
139 void _WriteBackComputedOutput(
151template <
typename DataManagerType>
154 std::vector< _OutputToExecute > *outputs,
161 outputs->push_back(_OutputToExecute(outputId));
171template <
typename DataManagerType>
176 const VdfRequest &computeRequest,
184 Base::_GetDataManager()->Resize(*schedule.
GetNetwork());
189 TfBits executedNodes(numNodes);
192 TfBits speculatedNodes(numNodes);
198 VdfRequest::IndexedView requestView(computeRequest);
199 for (
size_t i = 0; i < requestView.GetSize(); ++i) {
211 if (Base::_GetExecutor().GetOutputValue(output, mask)) {
212 callback(*maskedOutput, i);
216 _ExecuteOutputForSpeculation(
217 state, output, &executedNodes, &speculatedNodes);
220 if (Base::_GetExecutor().HasBeenInterrupted()) {
227 callback(*maskedOutput, i);
232template <
typename DataManagerType>
240 TF_DEBUG(VDF_SEE_TRACE).Msg(
"{ SpeculationOutputExecuteBegin();\n");
246 std::vector< _OutputToExecute > outputsStack;
253 std::vector< bool > speculated;
257 _PushBackOutputForSpeculation(&outputsStack, output, schedule);
259 bool hasBeenInterrupted = Base::_GetExecutor().HasBeenInterrupted();
261 while (!outputsStack.empty() && !hasBeenInterrupted) {
266 typename Base::_ExecutionStage stage = outputsStack.back().stage;
267 const size_t outputIndex = outputsStack.size() - 1;
274 bool previousStageSpeculated =
false;
275 while (outputsStack.back().numPushed) {
276 outputsStack.back().numPushed--;
277 previousStageSpeculated |= speculated.back();
278 speculated.pop_back();
283 case Base::ExecutionStageStart:
286 .Msg(
"{ SpeculationBeginNode(%p, \"%s\");\n",
293 if (
static_cast<const VdfSpeculationExecutorBase &
>(
294 Base::_GetExecutor()).IsSpeculatingNode(&node)) {
295 speculated.push_back(
true);
296 outputsStack.pop_back();
299 .Msg(
"SpeculationEndNodeSpeculationNode(); (cycle) }\n");
308 if (executedNodes->
IsSet(scheduleNodeIndex)) {
309 speculated.push_back(
310 speculatedNodes->
IsSet(scheduleNodeIndex));
311 outputsStack.pop_back();
314 .Msg(
"SpeculationEndNodeRedundantCompute(); }\n");
321 if (Base::_GetExecutor().GetOutputValue(
324 speculated.push_back(
false);
325 outputsStack.pop_back();
328 .Msg(
"SpeculationEndNodeFoundCache(); }\n");
337 outputsStack.back().stage = Base::ExecutionStagePreRequisitesDone;
342 if (input.input->GetSpec().IsPrerequisite()) {
343 const bool pushed = _PushBackOutputForSpeculation(
344 &outputsStack, *input.source, schedule);
345 outputsStack[outputIndex].numPushed += pushed;
352 if (outputsStack[outputIndex].numPushed > 0) {
357 case Base::ExecutionStagePreRequisitesDone:
364 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
371 outputsStack.back().stage = Base::ExecutionStageReadsDone;
375 if (affective && !previousStageSpeculated) {
390 const bool pushed = _PushBackOutputForSpeculation(
391 &outputsStack, *input.source, schedule);
392 outputsStack[outputIndex].numPushed += pushed;
400 if (outputsStack[outputIndex].numPushed > 0) {
404 case Base::ExecutionStageReadsDone:
407 outputsStack.back().stage = Base::ExecutionStageCompute;
410 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
415 input.input->GetAssociatedOutput();
426 const bool pushed = _PushBackOutputForSpeculation(
427 &outputsStack, *fromBufferOutput, schedule);
428 outputsStack[outputIndex].numPushed += pushed;
436 const bool pushed = _PushBackOutputForSpeculation(
437 &outputsStack, *input.source, schedule);
438 outputsStack[outputIndex].numPushed += pushed;
443 if (outputsStack[outputIndex].numPushed > 0) {
452 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
455 executedNodes->
Set(scheduleNodeIndex);
459 if (outputsStack.back().inputsSpeculate) {
462 .Msg(
"SpeculationSkipNode (cycle) (\"%s\"); }\n",
466 speculatedNodes->
Set(scheduleNodeIndex);
467 speculated.push_back(
true);
471 }
else if (affective) {
474 Base::_ComputeNode(state, node);
475 speculated.push_back(
false);
478 .Msg(
"SpeculationComputedNode(\"%s\"); }\n",
490 .Msg(
"SpeculationPassThrough(\"%s\"); }\n",
493 Base::_PassThroughNode(schedule, node);
494 speculated.push_back(
false);
499 hasBeenInterrupted = Base::_GetExecutor().HasBeenInterrupted();
513 VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
515 if (_writeBackExecutor &&
516 !hasBeenInterrupted &&
517 !outputsStack.back().inputsSpeculate) {
518 _WriteBackComputedOutput(output, outputId, schedule);
520 Base::_GetExecutor()._TouchOutput(output);
523 outputsStack.pop_back();
527 TF_DEBUG(VDF_SEE_TRACE).Msg(
"SpeculationOutputExecuteEnd(); }\n");
530template <
typename DataManagerType>
538 const typename Base::_DataHandle dataHandle =
539 Base::_GetDataManager()->GetDataHandle(output.GetId());
540 if (!Base::_GetDataManager()->IsValidDataHandle(dataHandle)) {
546 Base::_GetDataManager()->GetBufferData(dataHandle);
569 if (!output.GetAssociatedInput()) {
570 _writeBackExecutor->SetOutputValue(output, *value, computedMask);
597 const VdfMask *writeBackMask = &computedMask;
600 !_writeBackExecutor->HasInvalidationTimestampMismatch(
601 output, *passToOutput)) {
605 if (!writeBackMask->
IsEmpty()) {
606 _writeBackExecutor->SetOutputValue(output, *value, *writeBackMask);
611PXR_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.
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.