HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
speculationExecutor.h
Go to the documentation of this file.
1 //
2 // Copyright 2025 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_EXEC_VDF_SPECULATION_EXECUTOR_H
8 #define PXR_EXEC_VDF_SPECULATION_EXECUTOR_H
9 
10 ///\file
11 
12 #include "pxr/pxr.h"
13 
19 
20 #include "pxr/base/tf/diagnostic.h"
22 
24 
26 
27 ///////////////////////////////////////////////////////////////////////////////
28 ///
29 /// \class VdfSpeculationExecutor
30 ///
31 /// \brief Executor used in speculation.
32 ///
33 
34 template <
35  template <typename> class EngineType,
36  typename DataManagerType>
39  DataManagerType,
40  VdfSpeculationExecutorBase >
41 {
42  // Base class type
43  typedef
45  DataManagerType,
47  Base;
48 
49  // Executor factory.
50  typedef
54  _Factory;
55 
56 public:
57 
58  /// Constructs a speculation executor that was initiated from
59  /// \p speculationNode while being computed by \p parentExecutor.
60  ///
62  const VdfSpeculationNode *speculationNode,
63  const VdfExecutorInterface *parentExecutor);
64 
65  /// Construct a speculation executor with the given \p parentExecutor,
66  /// without registering a speculation node for cycle detection.
67  ///
69  const VdfExecutorInterface *parentExecutor) :
70  VdfSpeculationExecutor(nullptr, parentExecutor)
71  {}
72 
73  /// Destructor
74  ///
76 
77  /// Set the cached value for a given \p output.
78  ///
79  virtual void SetOutputValue(
80  const VdfOutput &output,
81  const VdfVector &value,
82  const VdfMask &mask) override final;
83 
84  /// Transfers ownership of \p value to the given \p output.
85  ///
86  virtual bool TakeOutputValue(
87  const VdfOutput &output,
89  const VdfMask &mask) override final;
90 
91  /// Returns the factory instance for this executor.
92  ///
93  virtual const VdfExecutorFactoryBase &GetFactory() const override final {
94  return _factory;
95  }
96 
97 private:
98 
99  // Run this executor with the given \p schedule and \p request.
100  //
101  virtual void _Run(
102  const VdfSchedule &schedule,
103  const VdfRequest &computeRequest,
104  VdfExecutorErrorLogger *errorLogger) override final;
105 
106  // Mark the output as having been visited. On speculation executors,
107  // we don't need to do anything other than notify the parent. Since this
108  // executor is temporary, we never do invalidation on it, and therefore
109  // can safely avoid doing the touching on the local data manager.
110  //
111  virtual void _TouchOutput(const VdfOutput &output) const override final {
113  }
114 
115 private:
116 
117  // The factory instance.
118  //
119  static const _Factory _factory;
120 
121  // This is the engine that will do most of our hard work for us.
122  //
123  EngineType<DataManagerType> _engine;
124 
125 };
126 
127 //////////////////////////////////////////////////////////////////////////////
128 
129 template <template <typename> class EngineType, typename DataManagerType>
132 
133 template <template <typename> class EngineType, typename DataManagerType>
135  const VdfSpeculationNode *speculationNode,
136  const VdfExecutorInterface *parentExecutor) :
137  Base(parentExecutor),
138  _engine(*this, &this->_dataManager)
139 {
140  // Apply the executors speculation node.
141  Base::_SetSpeculationNode(speculationNode);
142 
143  // Create sub stats on the parent executor and set them on this speculation
144  // executor. Set a nullptr if the parent does not have stats itself, or if
145  // speculationNode is a nullptr.
146  VdfExecutionStats *stats = parentExecutor->GetExecutionStats();
147  VdfExecutionStats *subStats = stats && speculationNode
148  ? stats->AddSubStat(&speculationNode->GetNetwork(), speculationNode)
149  : stats;
150  Base::SetExecutionStats(subStats);
151 
152  // Propagate the interruption flag from the parent executor to the
153  // speculation executor. This must be done in order to ensure that when the
154  // parent executor has been interrupted, execution will also be interrupted
155  // on the speculation executor.
157 }
158 
159 template <template <typename> class EngineType, typename DataManagerType>
160 void
162  const VdfOutput &output,
163  const VdfVector &value,
164  const VdfMask &mask)
165 {
166  // Call into the base class to set the output value.
167  Base::SetOutputValue(output, value, mask);
168 
169  // Make sure to also touch the output on the non-speculation-parent.
170  _TouchOutput(output);
171 }
172 
173 template <template <typename> class EngineType, typename DataManagerType>
174 bool
176  const VdfOutput &output,
177  VdfVector *value,
178  const VdfMask &mask)
179 {
180  // Call into the base class to take the output value.
181  const bool success = Base::TakeOutputValue(output, value, mask);
182 
183  // Make sure to also touch the output on the non-speculation-parent.
184  _TouchOutput(output);
185 
186  return success;
187 }
188 
189 template <template <typename> class EngineType, typename DataManagerType>
190 void
192  const VdfSchedule &schedule,
193  const VdfRequest &computeRequest,
194  VdfExecutorErrorLogger *errorLogger)
195 {
196  TRACE_FUNCTION();
197 
198  TF_VERIFY(Base::GetParentExecutor());
199  // Isolate tasks for speculation to ensure that they can make progress
200  // independently of parent execution tasks, i.e. threads that enter this
201  // isolated region will only be able to steal other speculation tasks
202  // spawned within the region. Note that main execution tasks are still
203  // free to steal tasks spawned from within this isolated region when idle,
204  // at which point they will become isolated until completion. This is a
205  // performance optimization that ensures idle threads are making progress
206  // on blocking tasks.
208  [&engine = _engine, &schedule, &computeRequest, errorLogger]() {
209  engine.RunSchedule(schedule, computeRequest, errorLogger);
210  });
211 }
212 
214 
215 #endif
VdfExecutionStats * GetExecutionStats() const
VdfSpeculationExecutor(const VdfExecutorInterface *parentExecutor)
const std::atomic_bool * GetInterruptionFlag() const
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
GLsizei const GLfloat * value
Definition: glcorearb.h:824
virtual void _TouchOutput(const VdfOutput &output) const =0
const VdfExecutorInterface * GetNonSpeculationParentExecutor() const
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
virtual bool TakeOutputValue(const VdfOutput &output, VdfVector *value, const VdfMask &mask) overridefinal
**But if you need a or simply need to know when the task has note that the like this
Definition: thread.h:626
Executor used in speculation.
PXR_NAMESPACE_OPEN_SCOPE auto WorkWithScopedParallelism(Fn &&fn, bool dropPythonGIL=true)
const VdfNetwork & GetNetwork() const
Definition: node.h:138
Contains a specification of how to execute a particular VdfNetwork.
Definition: schedule.h:40
GLint GLuint mask
Definition: glcorearb.h:124
#define TRACE_FUNCTION()
Definition: trace.h:30
void SetInterruptionFlag(const std::atomic_bool *interruptionFlag)
VdfSpeculationExecutor(const VdfSpeculationNode *speculationNode, const VdfExecutorInterface *parentExecutor)
A node that pulls on a vector of value that are downstream of the current execution position...
virtual const VdfExecutorFactoryBase & GetFactory() const overridefinal
virtual void SetOutputValue(const VdfOutput &output, const VdfVector &value, const VdfMask &mask) overridefinal
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
void SetExecutionStats(VdfExecutionStats *stats)
VDF_API VdfExecutionStats * AddSubStat(const VdfNetwork *network, const VdfNode *invokingNode)
Abstract base class for classes that execute a VdfNetwork to compute a requested set of values...
void _SetSpeculationNode(const VdfNode *speculationNode)