Jump to content

Runtime Parameter Updates

From RidgeRun Developer Wiki

🚧 Documentation is under development

The Holoscan SDK guide is currently under active development. Some sections may be incomplete or change without notice.

Questions? Contact RidgeRun or email to support@ridgerun.com.

Contents Pin





Runtime Parameter Updates

Some application settings are known before compilation, while others need to change during a run. A bounded scalar can be updated while the graph is active when its operator schema and compiled plan admit that behavior. Resource preparation, topology, and capacity changes follow different paths.

Use the parameter schema to define the setting first. An admitted update prepares a new immutable parameter generation, which the runtime publishes at an allowed boundary. A compute callback keeps the generation it started with for that activation.

The schema, compiled plan, and caller's access policy must all permit the update. Acceptance, publication, and observation are separate steps; the application needs to check the outcome of each.


Advanced runtime topic
Start with values configured before compilation. Use live updates when a bounded scalar must change without rebuilding the graph, and move to lifecycle control or a new plan when the change affects preparation, topology, or capacity.


Decide whether the change is live

Choose the path from the kind of change the application needs:

Change needed Use this path
A value is selected before the graph is compiled Typed Parameters and Configuration
A bounded scalar must change at a future compute boundary Runtime parameter updates on this page
A resource must be released, rebuilt, or reacquired Lifecycle Callbacks and Restart Control
Ports, topology, or admitted capacity must change Stop the session, build a new graph, compile a new plan, and run it

The Runtime Parameters in the NVIDIA Holoscan SDK documentation provides the official live-update introduction. The rest of this page explains the bounded application path and the checks that make a change safe to use.

Admit Live Changes Before Starting the Session

Mark a field with runtime_mutable() only when the operator can safely use a changed value at a future compute boundary. The marker does not itself grant authority or allocate update capacity. The runtime-parameters demo uses:

struct GainParams {
  float gain{1.0F};
};

HOLOSCAN_PARAM_SCHEMA(
    GainParams,
    holoscan::param_schema("com.nvidia.holoscan.examples.RuntimeGainParams", 1),
    holoscan::field<&GainParams::gain>("gain")
        .runtime_mutable()
        .range(0.0F, 8.0F));

The demo opts into ParameterCompileOptions through options.parameters.runtime_updates = ParamRuntimeUpdatePolicy::kEnabledIfAdmitted on its Standard-profile compile options. Compilation must admit the field and reserve bounded generation, pending-update and observer storage. Check plan diagnostics; selecting a policy does not make every schema field updateable.

Compile-time and recompile-required fields remain frozen for the accepted plan. Existing vision operators whose schemas only declare these policies do not gain hot-swappable crop dimensions or backend settings through this API. A lifecycle-mutable field uses the transaction mechanism described in Lifecycle Callbacks and Restart Control.

Resolve the Field in the Active Run

Find the desired field in the accepted plan's parameter catalog, resolve its owning operator through RunSession::operator_ref(), and combine that run-bound reference with the catalog field ID in a ParamAddress. Avoid guessed field IDs and references from another plan or session.

Mint a parameter_control() handle with an explicit ParamAccessPolicy. The runtime demo grants local application read, update, await, capture and observe permissions; a production caller can use a narrower scope. Actor and reason identifiers provide audit evidence, not authorization.

This submission fragment assumes an authorized handle and a resolved gain address:

const auto accepted = handle.submit(holoscan::ParamPatch{
    .target = gain_address,
    .value = holoscan::ParamValue::from(2.0F),
});
if (!accepted.committed) {
  // Inspect the rejection result; no candidate was accepted.
  return 1;
}
const auto terminal = handle.await(
    accepted.update_sequence, std::chrono::milliseconds{250});
// Check terminal before inspecting its publication state.

The owning submit() API accepts fixed scalar patches. It does not replace a string, container, pointer or arbitrary resource handle. A same-operator batch is all-or-nothing; a cross-operator batch is rejected. The optional expected_generation precondition compares with the latest accepted generation, which may be ahead of the published generation.

Distinguish Acceptance, Publication and Observation

State Meaning
Accepted A complete candidate and update sequence have been reserved. The current callback still uses its pinned generation.
AcceptedNoChange The request produces no effective change; inspect its result without waiting for a new generation to appear.
Published The candidate is available for a later admitted compute callback. Publication is a terminal state for await.
Observed A later callback has pinned the published generation. This can occur after await has already returned.

await() waits for terminalization, not necessarily observation. A timeout limits the caller's wait and does not cancel the update. Check the returned result and state before using the generation. Reads can select Published, LatestAccepted or Pending views; they answer different questions about current execution and queued intent.


Acceptance Is Not Immediate Effect
The committed flag reserves a candidate. It does not mean the new value has been published or used by a compute callback. Confirm the relevant state and, when needed, observe params_generation() inside later processing.


The runtime revalidates the complete candidate against the admitted schema and plan constraints. A field-range check is only part of admission: derived contracts, retained bounds, access, stale references and available storage can also reject the request. QueueFull is a bounded-capacity outcome, not permission to allocate more storage in compute. Recompilation is required when the proposed change exceeds what the plan admitted.

Submit from Compute Without Waiting

Inside compute, use ExecutionContext::param_control() and its try_submit_from_compute() facade. It copies fixed ParamInlinePatch records without allocation and never waits. Submitted means the inline request was enqueued; its update sequence is not yet assigned. Later draining performs admission. QueueFull can mean bounded storage is full or the control lock was unavailable.

Do not call the owning handle's submission or await methods from a runtime callback. A callback-origin update targets a future generation, and the facade expires when that callback returns. It cannot perform general parameter reads, close ingress or grant restart authority.

Observe Changes and Close Update Ingress

Open an event cursor before submitting if you need the transition history. A cursor has bounded retention; a reported gap requires explicit resynchronization from current state, without assuming every transition was delivered. Observer scope and capacity are part of the access policy and accepted plan.

close_parameter_update_ingress() installs a stop fence for this ingress. Previously accepted work is handled according to the fence, and later submissions are rejected as closed. It is not a temporary pause that can be reopened on the same session.


Related examples and concepts

Examples

  • Runtime parameters demo demonstrates gain updates, published reads, a stale-generation rejection, event observation and ingress closure.

Concepts


Cookies help us deliver our services. By using our services, you agree to our use of cookies.