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) {
262 typename Base::_ExecutionStage stage = outputsStack.back().stage;
263 const size_t outputIndex = outputsStack.size() - 1;
270 bool previousStageSpeculated =
false;
271 while (outputsStack.back().numPushed) {
272 outputsStack.back().numPushed--;
273 previousStageSpeculated |= speculated.back();
274 speculated.pop_back();
279 case Base::ExecutionStageStart:
282 .Msg(
"{ SpeculationBeginNode(%p, \"%s\");\n",
289 if (
static_cast<const VdfSpeculationExecutorBase &
>(
290 Base::_GetExecutor()).IsSpeculatingNode(&node)) {
291 speculated.push_back(
true);
292 outputsStack.pop_back();
295 .Msg(
"SpeculationEndNodeSpeculationNode(); (cycle) }\n");
305 speculated.push_back(speculatedNodes->
IsSet(
307 outputsStack.pop_back();
310 .Msg(
"SpeculationEndNodeRedundantCompute(); }\n");
317 if (Base::_GetExecutor().GetOutputValue(
320 speculated.push_back(
false);
321 outputsStack.pop_back();
324 .Msg(
"SpeculationEndNodeFoundCache(); }\n");
333 outputsStack.back().stage = Base::ExecutionStagePreRequisitesDone;
338 if (input.input->GetSpec().IsPrerequisite()) {
339 const bool pushed = _PushBackOutputForSpeculation(
340 &outputsStack, *input.source, schedule);
341 outputsStack[outputIndex].numPushed += pushed;
348 if (outputsStack[outputIndex].numPushed > 0) {
353 case Base::ExecutionStagePreRequisitesDone:
360 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
367 outputsStack.back().stage = Base::ExecutionStageReadsDone;
371 if (affective && !previousStageSpeculated) {
386 const bool pushed = _PushBackOutputForSpeculation(
387 &outputsStack, *input.source, schedule);
388 outputsStack[outputIndex].numPushed += pushed;
396 if (outputsStack[outputIndex].numPushed > 0) {
400 case Base::ExecutionStageReadsDone:
403 outputsStack.back().stage = Base::ExecutionStageCompute;
406 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
411 input.input->GetAssociatedOutput();
422 const bool pushed = _PushBackOutputForSpeculation(
423 &outputsStack, *fromBufferOutput, schedule);
424 outputsStack[outputIndex].numPushed += pushed;
432 const bool pushed = _PushBackOutputForSpeculation(
433 &outputsStack, *input.source, schedule);
434 outputsStack[outputIndex].numPushed += pushed;
439 if (outputsStack[outputIndex].numPushed > 0) {
448 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
455 if (outputsStack.back().inputsSpeculate) {
458 .Msg(
"SpeculationSkipNode (cycle) (\"%s\"); }\n",
463 speculated.push_back(
true);
467 }
else if (affective) {
470 Base::_ComputeNode(state, node);
471 speculated.push_back(
false);
474 .Msg(
"SpeculationComputedNode(\"%s\"); }\n",
486 .Msg(
"SpeculationPassThrough(\"%s\"); }\n",
489 Base::_PassThroughNode(schedule, node);
490 speculated.push_back(
false);
495 hasBeenInterrupted = Base::_GetExecutor().HasBeenInterrupted();
509 VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
511 if (_writeBackExecutor &&
512 !hasBeenInterrupted &&
513 !outputsStack.back().inputsSpeculate) {
514 _WriteBackComputedOutput(output, outputId, schedule);
516 Base::_GetExecutor()._TouchOutput(output);
519 outputsStack.pop_back();
523 TF_DEBUG(VDF_SEE_TRACE).Msg(
"SpeculationOutputExecuteEnd(); }\n");
526template <
typename DataManagerType>
534 const typename Base::_DataHandle dataHandle =
535 Base::_GetDataManager()->GetDataHandle(output.
GetId());
536 if (!Base::_GetDataManager()->IsValidDataHandle(dataHandle)) {
542 Base::_GetDataManager()->GetBufferData(dataHandle);
566 _writeBackExecutor->SetOutputValue(output, *value, computedMask);
593 const VdfMask *writeBackMask = &computedMask;
596 !_writeBackExecutor->HasInvalidationTimestampMismatch(
597 output, *passToOutput)) {
601 if (!writeBackMask->
IsEmpty()) {
602 _writeBackExecutor->SetOutputValue(output, *value, *writeBackMask);
607PXR_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.
size_t GetNodeCapacity() const
Returns the number of entries currently available for nodes and for which it is valid to call GetNode...
This is the base class for all nodes in a VdfNetwork.
static VdfIndex GetIndexFromId(const VdfId id)
Get the node index from the node id.
VDF_API const std::string GetDebugName() const
Returns the debug name for this node, if one is registered.
VdfId GetId() const
Returns the unique id of this node in its network.
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.
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.
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.