MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
ComputeMatrix.hpp
Go to the documentation of this file.
1#pragma once
2
6
8#include <execution>
9
10namespace MayaFlux::Yantra {
11
12/**
13 * @enum ExecutionPolicy
14 * @brief Policy for execution strategy selection
15 */
16enum class ExecutionPolicy : uint8_t {
17 CONSERVATIVE, // Prefer safety and predictability
18 BALANCED, // Balance between performance and safety
19 AGGRESSIVE // Maximize performance
20};
21
22/**
23 * @class ComputeMatrix
24 * @brief Local execution orchestrator for computational operations
25 *
26 * ComputeMatrix provides a self-contained execution environment for operations.
27 * It maintains its own operation instances and execution strategies without
28 * relying on any global registries. Each matrix instance is independent.
29 *
30 * Key Design Principles:
31 * - Instance-local operation management
32 * - Focus on execution patterns and strategies
33 * - Clean separation from registration concerns
34 *
35 * Core Responsibilities:
36 * - Execute operations with various strategies (sync, async, parallel, chain)
37 * - Manage instance-local named operations
38 * - Provide fluent interface through FluentExecutor
39 * - Configure execution contexts for optimization
40 */
41class MAYAFLUX_API ComputeMatrix : public std::enable_shared_from_this<ComputeMatrix> {
42public:
43 /**
44 * @brief Create a new ComputeMatrix instance
45 */
46 static std::shared_ptr<ComputeMatrix> create()
47 {
48 return std::make_shared<ComputeMatrix>();
49 }
50
51 /**
52 * @brief Add a pre-configured operation instance to this matrix
53 * @tparam OpClass Operation class type
54 * @param name Unique name within this matrix
55 * @param operation Shared pointer to the operation
56 * @return true if added successfully
57 */
58 template <typename OpClass>
59 bool add_operation(const std::string& name, std::shared_ptr<OpClass> operation)
60 {
61 if (!operation)
62 return false;
63 return m_operations.add(name, operation);
64 }
65
66 /**
67 * @brief Create and add an operation to this matrix
68 * @tparam OpClass Operation class type
69 * @tparam Args Constructor argument types
70 * @param name Unique name within this matrix
71 * @param args Constructor arguments
72 * @return Shared pointer to the created operation
73 */
74 template <typename OpClass, typename... Args>
75 std::shared_ptr<OpClass> create_operation(const std::string& name, Args&&... args)
76 {
77 auto operation = std::make_shared<OpClass>(std::forward<Args>(args)...);
78 if (m_operations.add(name, operation)) {
79 return operation;
80 }
81 return nullptr;
82 }
83
84 /**
85 * @brief Get a named operation from this matrix
86 * @tparam OpClass Expected operation type
87 * @param name Operation name
88 * @return Shared pointer to operation or nullptr
89 */
90 template <typename OpClass>
91 std::shared_ptr<OpClass> get_operation(const std::string& name)
92 {
93 return m_operations.get<OpClass>(name);
94 }
95
96 /**
97 * @brief Remove a named operation from this matrix
98 * @param name Operation name to remove
99 * @return true if removed successfully
100 */
101 bool remove_operation(const std::string& name)
102 {
103 return m_operations.remove(name);
104 }
105
106 /**
107 * @brief List all operation names in this matrix
108 * @return Vector of operation names
109 */
110 std::vector<std::string> list_operations() const
111 {
112 return m_operations.list_names();
113 }
114
115 /**
116 * @brief Clear all operations from this matrix
117 */
119 {
120 m_operations.clear();
121 }
122
123 /**
124 * @brief Execute an operation by creating a new instance
125 * @tparam OpClass Operation class to instantiate and execute
126 * @tparam Datum InputType Input data type
127 * @tparam Datum OutputType Output data type
128 * @param input Input data
129 * @param args Constructor arguments for the operation
130 * @return Optional containing result or nullopt on failure
131 */
132 template <typename OpClass, ComputeData InputType, ComputeData OutputType = InputType, typename... Args>
133 std::optional<Datum<OutputType>> execute(const Datum<InputType>& input, Args&&... args)
134 {
135 auto operation = std::make_shared<OpClass>(std::forward<Args>(args)...);
136 return execute_operation<OpClass, InputType, OutputType>(operation, input);
137 }
138
139 /**
140 * @brief Execute a named operation from the pool
141 * @tparam OpClass Operation class type
142 * @tparam Datum InputType Input data type
143 * @tparam Datum OutputType Output data type
144 * @param name Name of the operation
145 * @param input Input data
146 * @return Optional containing result or nullopt on failure
147 */
148 template <typename OpClass, ComputeData InputType, ComputeData OutputType = InputType>
149 std::optional<Datum<OutputType>> execute_named(const std::string& name, const Datum<InputType>& input)
150 {
151 auto operation = m_operations.get<OpClass>(name);
152 if (!operation)
153 return std::nullopt;
154 return execute_operation<OpClass, InputType, OutputType>(operation, input);
155 }
156
157 /**
158 * @brief Execute with provided operation instance
159 * @tparam OpClass Operation class type
160 * @tparam Datum InputType Input data type
161 * @tparam Datum OutputType Output data type
162 * @param operation Operation instance to execute
163 * @param input Input data
164 * @return Optional containing result or nullopt on failure
165 */
166 template <typename OpClass, ComputeData InputType, ComputeData OutputType = InputType>
167 std::optional<Datum<OutputType>> execute_with(std::shared_ptr<OpClass> operation, const Datum<InputType>& input)
168 {
169 return execute_operation<OpClass, InputType, OutputType>(operation, input);
170 }
171
172 /**
173 * @brief Execute operation asynchronously
174 * @tparam OpClass Operation class type
175 * @tparam InputType Input data type
176 * @tparam OutputType Output data type
177 * @param input Input data
178 * @param args Constructor arguments
179 * @return Future containing the result
180 */
181 template <typename OpClass, ComputeData InputType, ComputeData OutputType = InputType, typename... Args>
182 std::future<std::optional<Datum<OutputType>>> execute_async(const Datum<InputType>& input, Args&&... args)
183 {
184 return std::async(std::launch::async, [this, input, args...]() {
185 return execute<OpClass, InputType, OutputType>(input, args...);
186 });
187 }
188
189 /**
190 * @brief Execute named operation asynchronously
191 */
192 template <typename OpClass, ComputeData InputType, ComputeData OutputType = InputType>
193 std::future<std::optional<Datum<OutputType>>> execute_named_async(const std::string& name, const Datum<InputType>& input)
194 {
195 return std::async(std::launch::async, [this, name, input]() {
196 return execute_named<OpClass, InputType, OutputType>(name, input);
197 });
198 }
199
200 /**
201 * @brief Execute multiple operations in parallel
202 * @tparam InputType Input data type
203 * @tparam OpClasses Operation classes to execute
204 * @param input Input data
205 * @return Tuple of results from each operation
206 */
207 template <ComputeData InputType, typename... OpClasses>
209 {
210 return std::make_tuple(
211 execute_async<OpClasses, InputType>(input).get()...);
212 }
213
214 /**
215 * @brief Execute multiple named operations in parallel
216 * @tparam OpClass Base operation class
217 * @tparam InputType Input data type
218 * @tparam OutputType Output data type
219 * @param names Vector of operation names
220 * @param input Input data
221 * @return Vector of results
222 */
223 template <typename OpClass, ComputeData InputType, ComputeData OutputType = InputType>
224 std::vector<std::optional<Datum<OutputType>>> execute_parallel_named(
225 const std::vector<std::string>& names,
226 const Datum<InputType>& input)
227 {
228 std::vector<std::future<std::optional<Datum<OutputType>>>> futures;
229 futures.reserve(names.size());
230
231 for (const auto& name : names) {
232 futures.push_back(execute_named_async<OpClass, InputType, OutputType>(name, input));
233 }
234
235 std::vector<std::optional<Datum<OutputType>>> results;
236 results.reserve(futures.size());
237
238 for (auto& future : futures) {
239 results.push_back(future.get());
240 }
241
242 return results;
243 }
244
245 /**
246 * @brief Execute operations in sequence (type-safe chain)
247 * @tparam FirstOp First operation type
248 * @tparam SecondOp Second operation type
249 * @tparam InputType Initial input type
250 * @tparam IntermediateType Type between operations
251 * @tparam OutputType Final output type
252 * @param input Initial input
253 * @return Optional containing final result
254 */
255 template <typename FirstOp, typename SecondOp,
256 ComputeData InputType,
257 ComputeData IntermediateType,
258 ComputeData OutputType>
259 std::optional<Datum<OutputType>> execute_chain(const Datum<InputType>& input)
260 {
261 auto first_result = execute<FirstOp, InputType, IntermediateType>(input);
262 if (!first_result)
263 return std::nullopt;
264
265 return execute<SecondOp, IntermediateType, OutputType>(*first_result);
266 }
267
268 /**
269 * @brief Execute named operations in sequence
270 */
271 template <typename FirstOp, typename SecondOp,
272 ComputeData InputType,
273 ComputeData IntermediateType,
274 ComputeData OutputType>
275 std::optional<Datum<OutputType>> execute_chain_named(
276 const std::string& first_name,
277 const std::string& second_name,
278 const Datum<InputType>& input)
279 {
280 auto first_result = execute_named<FirstOp, InputType, IntermediateType>(first_name, input);
281 if (!first_result)
282 return std::nullopt;
283
284 return execute_named<SecondOp, IntermediateType, OutputType>(second_name, *first_result);
285 }
286
287 /**
288 * @brief Execute operation on multiple inputs
289 * @tparam OpClass Operation class
290 * @tparam InputType Input data type
291 * @tparam OutputType Output data type
292 * @param inputs Vector of inputs
293 * @param args Constructor arguments for operation
294 * @return Vector of results
295 */
296 template <typename OpClass, ComputeData InputType, ComputeData OutputType = InputType, typename... Args>
297 std::vector<std::optional<Datum<OutputType>>> execute_batch(
298 const std::vector<Datum<InputType>>& inputs,
299 Args&&... args)
300 {
301 auto operation = std::make_shared<OpClass>(std::forward<Args>(args)...);
302
303 std::vector<std::optional<Datum<OutputType>>> results;
304 results.reserve(inputs.size());
305
306 for (const auto& input : inputs) {
307 results.push_back(execute_operation<OpClass, InputType, OutputType>(operation, input));
308 }
309
310 return results;
311 }
312
313 /**
314 * @brief Execute operation on multiple inputs in parallel
315 */
316 template <typename OpClass, ComputeData InputType, ComputeData OutputType = InputType, typename... Args>
317 std::vector<std::optional<Datum<OutputType>>> execute_batch_parallel(
318 const std::vector<Datum<InputType>>& inputs,
319 Args&&... args)
320 {
321 auto operation = std::make_shared<OpClass>(std::forward<Args>(args)...);
322
323 std::vector<std::optional<Datum<OutputType>>> results(inputs.size());
324
325 std::transform(std::execution::par_unseq,
326 inputs.begin(), inputs.end(),
327 results.begin(),
328 [this, operation](const Datum<InputType>& input) {
329 return execute_operation<OpClass, InputType, OutputType>(operation, input);
330 });
331
332 return results;
333 }
334
335 /**
336 * @brief Create a fluent executor for chaining operations
337 * @tparam StartType Initial data type
338 * @param input Initial input data
339 * @return FluentExecutor for this matrix
340 */
341 template <ComputeData StartType>
346
347 template <ComputeData StartType>
349 {
350 return with(Datum<StartType>(input));
351 }
352
353 /**
354 * @brief Create a fluent executor with move semantics
355 */
356
357 template <ComputeData StartType>
362
363 template <ComputeData StartType>
365 {
366 return with(Datum<StartType>(std::forward<StartType>(input)));
367 }
368
369 /**
370 * @brief Execute an operation chain asynchronously.
371 *
372 * @p chain receives a FluentExecutor seeded with @p input and must return
373 * the terminal Datum. The entire sequence runs on a background thread.
374 * @p on_complete is invoked with the result on that same thread.
375 *
376 * The future is owned by this matrix instance. drain_async() and the
377 * destructor guarantee all in-flight chains finish before the matrix
378 * is destroyed. No thread management is required by the caller.
379 *
380 * @code
381 * matrix->with_async(make_granular_input(container),
382 * [](auto chain) {
383 * return chain.then<SegmentOp>("segment")
384 * .then<AttributeOp>("attribute")
385 * .then<SortOp>("sort")
386 * .to_io();
387 * },
388 * [ex](Datum<Kakshya::RegionGroup> result) {
389 * ex->grains = std::move(result);
390 * ex->ready = true;
391 * });
392 * @endcode
393 *
394 * @tparam StartType Input data type.
395 * @tparam ChainFunc Callable: (FluentExecutor<ComputeMatrix, StartType>) -> Datum<ResultType>.
396 * @tparam CompleteFn Callable: (Datum<R>) -> void, where R is deduced from ChainFunc.
397 * @param input Seed datum for the chain.
398 * @param chain Lambda describing the full operation sequence.
399 * @param on_complete Called with the final Datum on completion.
400 */
401 template <ComputeData StartType, typename ChainFunc, typename CompleteFn>
402 void with_async(Datum<StartType> input, ChainFunc&& chain, CompleteFn&& on_complete)
403 {
404 auto self = shared_from_this();
405 register_async(std::async(std::launch::async,
406 [self,
407 input = std::move(input),
408 chain = std::forward<ChainFunc>(chain),
409 on_complete = std::forward<CompleteFn>(on_complete)]() mutable {
410 on_complete(chain(
412 }));
413 }
414
415 template <ComputeData StartType, typename ChainFunc, typename CompleteFn>
416 void with_async(StartType input, ChainFunc&& chain, CompleteFn&& on_complete)
417 {
418 with_async(Datum<StartType>(std::move(input)),
419 std::forward<ChainFunc>(chain),
420 std::forward<CompleteFn>(on_complete));
421 }
422
423 /**
424 * @brief Set execution policy for this matrix
425 * @param policy Execution policy to use
426 */
428 {
429 m_execution_policy = policy;
430 }
431
432 /**
433 * @brief Get current execution policy
434 */
436 {
437 return m_execution_policy;
438 }
439
440 /**
441 * @brief Enable/disable execution profiling
442 */
443 void set_profiling(bool enabled)
444 {
445 m_profiling_enabled = enabled;
446 }
447
448 /**
449 * @brief Get execution statistics
450 */
451 std::unordered_map<std::string, std::any> get_statistics() const
452 {
453 auto stats = m_operations.get_statistics();
454 stats["total_executions"] = m_total_executions.load();
455 stats["failed_executions"] = m_failed_executions.load();
456 if (m_profiling_enabled) {
457 stats["average_execution_time_ms"] = m_average_execution_time.load();
458 }
459 return stats;
460 }
461
462 /**
463 * @brief Set custom context configurator
464 * @param configurator Function to configure execution contexts
465 */
467 std::function<void(ExecutionContext&, const std::type_index&)> configurator)
468 {
469 m_context_configurator = std::move(configurator);
470 }
471
472 /**
473 * @brief Set default execution timeout
474 * @param timeout Timeout duration
475 */
476 void set_default_timeout(std::chrono::milliseconds timeout)
477 {
478 m_default_timeout = timeout;
479 }
480
482 : m_async_tasks([this](std::exception_ptr ep) { handle_async_error(std::move(ep)); })
483 {
484 }
485
486private:
487 /**
488 * @brief Core execution implementation
489 */
490 template <typename OpClass, ComputeData InputType, ComputeData OutputType>
491 std::optional<Datum<OutputType>> execute_operation(
492 std::shared_ptr<OpClass> operation,
493 const Datum<InputType>& input)
494 {
495 if (!operation)
496 return std::nullopt;
497
498 m_total_executions++;
499
500 try {
502 configure_execution_context(ctx, std::type_index(typeid(OpClass)));
503
504 auto start = std::chrono::steady_clock::now();
505
506 auto result = operation->apply_operation_internal(input, ctx);
507
508 if (m_profiling_enabled) {
509 auto end = std::chrono::steady_clock::now();
510 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
511 update_execution_time(duration.count());
512 }
513
514 return result;
515
516 } catch (const std::exception& e) {
517 m_failed_executions++;
518 handle_execution_error(e, std::type_index(typeid(OpClass)));
519 return std::nullopt;
520 }
521 }
522
523 /**
524 * @brief Configure execution context based on operation type and policy
525 */
526 void configure_execution_context(ExecutionContext& ctx, const std::type_index& op_type)
527 {
528 switch (m_execution_policy) {
529 case ExecutionPolicy::CONSERVATIVE:
530 case ExecutionPolicy::BALANCED:
531 ctx.mode = ExecutionMode::SYNC;
532 break;
533 case ExecutionPolicy::AGGRESSIVE:
534 ctx.mode = ExecutionMode::PARALLEL;
535 break;
536 }
537
538 ctx.timeout = m_default_timeout;
539
540 if (m_context_configurator) {
541 m_context_configurator(ctx, op_type);
542 }
543
544 // TODO: Add thread pool assignment, GPU context, etc.
545 }
546
547 /**
548 * @brief Handle execution errors
549 */
550 void handle_execution_error(const std::exception& e, const std::type_index& op_type)
551 {
552 m_last_error = e.what();
553 m_last_error_type = op_type;
554
555 if (m_error_callback) {
556 m_error_callback(e, op_type);
557 }
558 }
559
560 /**
561 * @brief Update execution time statistics
562 */
563 void update_execution_time(double ms)
564 {
565 double current_avg = m_average_execution_time.load();
566 double total_execs = m_total_executions.load();
567 double new_avg = (current_avg * (total_execs - 1) + ms) / total_execs;
568 m_average_execution_time.store(new_avg);
569 }
570
571 void register_async(std::future<void> f)
572 {
573 m_async_tasks.submit(std::move(f));
574 }
575
576 /**
577 * @brief Routes an async chain's exception into the same reporting
578 * surface as a synchronous operation failure.
579 *
580 * There is no single operation type to attribute the failure to here,
581 * since the exception may have escaped the chain itself rather than
582 * one operation's apply_operation_internal(). typeid(void) marks that
583 * absence, matching m_last_error_type's own default.
584 */
585 void handle_async_error(std::exception_ptr ep)
586 {
587 try {
588 std::rethrow_exception(std::move(ep));
589 } catch (const std::exception& e) {
590 handle_execution_error(e, typeid(void));
591 } catch (...) {
592 m_last_error = "async chain failed with unrecognized exception";
593 m_last_error_type = typeid(void);
594 }
595 }
596
598
599 ExecutionPolicy m_execution_policy = ExecutionPolicy::BALANCED;
600 std::chrono::milliseconds m_default_timeout { 0 };
601 std::function<void(ExecutionContext&, const std::type_index&)> m_context_configurator;
602
603 std::atomic<size_t> m_total_executions { 0 };
604 std::atomic<size_t> m_failed_executions { 0 };
605 std::atomic<double> m_average_execution_time { 0.0 };
606 bool m_profiling_enabled = false;
607
609
610 std::string m_last_error;
611 std::type_index m_last_error_type { typeid(void) };
612 std::function<void(const std::exception&, const std::type_index&)> m_error_callback;
613
614public:
615 /**
616 * @brief Set error callback
617 */
619 std::function<void(const std::exception&, const std::type_index&)> callback)
620 {
621 m_error_callback = std::move(callback);
622 }
623
624 /**
625 * @brief Get last error message
626 */
627 std::string get_last_error() const
628 {
629 return m_last_error;
630 }
631
632 /**
633 * @brief Block until all in-flight async chains complete.
634 *
635 * Called automatically by the destructor. May also be called explicitly
636 * before teardown of any resource a chain callback might write into.
637 */
639 {
640 m_async_tasks.drain();
641 }
642
644 {
645 drain_async();
646 }
647};
648
649} // namespace MayaFlux::Yantra
Core::GlobalInputConfig input
Definition Config.cpp:42
BufferProcessingChain * chain
PickCallback callback
Definition Picker.cpp:22
std::string name
Definition VKDevice.cpp:123
void drain()
Blocks until every currently submitted future completes.
Owns a set of in-flight std::async futures on behalf of a subsystem.
std::unordered_map< std::string, std::any > get_statistics() const
Get execution statistics.
std::vector< std::optional< Datum< OutputType > > > execute_batch(const std::vector< Datum< InputType > > &inputs, Args &&... args)
Execute operation on multiple inputs.
std::vector< std::optional< Datum< OutputType > > > execute_parallel_named(const std::vector< std::string > &names, const Datum< InputType > &input)
Execute multiple named operations in parallel.
ExecutionPolicy get_execution_policy() const
Get current execution policy.
void update_execution_time(double ms)
Update execution time statistics.
std::future< std::optional< Datum< OutputType > > > execute_named_async(const std::string &name, const Datum< InputType > &input)
Execute named operation asynchronously.
FluentExecutor< ComputeMatrix, StartType > with(StartType &&input)
std::optional< Datum< OutputType > > execute_named(const std::string &name, const Datum< InputType > &input)
Execute a named operation from the pool.
std::optional< Datum< OutputType > > execute_chain(const Datum< InputType > &input)
Execute operations in sequence (type-safe chain)
void set_context_configurator(std::function< void(ExecutionContext &, const std::type_index &)> configurator)
Set custom context configurator.
std::shared_ptr< OpClass > get_operation(const std::string &name)
Get a named operation from this matrix.
void with_async(StartType input, ChainFunc &&chain, CompleteFn &&on_complete)
std::future< std::optional< Datum< OutputType > > > execute_async(const Datum< InputType > &input, Args &&... args)
Execute operation asynchronously.
void set_error_callback(std::function< void(const std::exception &, const std::type_index &)> callback)
Set error callback.
std::string get_last_error() const
Get last error message.
void configure_execution_context(ExecutionContext &ctx, const std::type_index &op_type)
Configure execution context based on operation type and policy.
std::vector< std::optional< Datum< OutputType > > > execute_batch_parallel(const std::vector< Datum< InputType > > &inputs, Args &&... args)
Execute operation on multiple inputs in parallel.
std::function< void(const std::exception &, const std::type_index &)> m_error_callback
FluentExecutor< ComputeMatrix, StartType > with(const Datum< StartType > &input)
Create a fluent executor for chaining operations.
std::vector< std::string > list_operations() const
List all operation names in this matrix.
void set_profiling(bool enabled)
Enable/disable execution profiling.
std::shared_ptr< OpClass > create_operation(const std::string &name, Args &&... args)
Create and add an operation to this matrix.
std::optional< Datum< OutputType > > execute_with(std::shared_ptr< OpClass > operation, const Datum< InputType > &input)
Execute with provided operation instance.
void handle_execution_error(const std::exception &e, const std::type_index &op_type)
Handle execution errors.
void set_default_timeout(std::chrono::milliseconds timeout)
Set default execution timeout.
void set_execution_policy(ExecutionPolicy policy)
Set execution policy for this matrix.
std::optional< Datum< OutputType > > execute(const Datum< InputType > &input, Args &&... args)
Execute an operation by creating a new instance.
void register_async(std::future< void > f)
std::optional< Datum< OutputType > > execute_chain_named(const std::string &first_name, const std::string &second_name, const Datum< InputType > &input)
Execute named operations in sequence.
void handle_async_error(std::exception_ptr ep)
Routes an async chain's exception into the same reporting surface as a synchronous operation failure.
bool add_operation(const std::string &name, std::shared_ptr< OpClass > operation)
Add a pre-configured operation instance to this matrix.
void clear_operations()
Clear all operations from this matrix.
FluentExecutor< ComputeMatrix, StartType > with(Datum< StartType > &&input)
Create a fluent executor with move semantics.
void with_async(Datum< StartType > input, ChainFunc &&chain, CompleteFn &&on_complete)
Execute an operation chain asynchronously.
Parallel::AsyncGroup< void > m_async_tasks
std::function< void(ExecutionContext &, const std::type_index &)> m_context_configurator
auto execute_parallel(const Datum< InputType > &input)
Execute multiple operations in parallel.
FluentExecutor< ComputeMatrix, StartType > with(const StartType &input)
std::optional< Datum< OutputType > > execute_operation(std::shared_ptr< OpClass > operation, const Datum< InputType > &input)
Core execution implementation.
void drain_async()
Block until all in-flight async chains complete.
bool remove_operation(const std::string &name)
Remove a named operation from this matrix.
static std::shared_ptr< ComputeMatrix > create()
Create a new ComputeMatrix instance.
Local execution orchestrator for computational operations.
Fluent interface for chaining operations on any executor.
Thread-safe pool for managing named operation instances.
Universal concept for types that can flow through the computation pipeline.
Definition DataSpec.hpp:74
ExecutionPolicy
Policy for execution strategy selection.
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:26
ExecutionMode mode
Execution mode controlling scheduling behavior.
std::chrono::milliseconds timeout
Optional timeout for operation execution.
Context information controlling how a compute operation executes.