NVIDIA Holoscan SDK v2.9.0

GXF 调度器

图中实体的执行由调度器以及与每个实体关联的调度项管理。调度器是负责协调图中定义的所有实体执行的组件。调度器通常跟踪图实体及其当前的执行状态,并在准备好执行时将它们传递给 nvidia::gxf::EntityExecutor 组件。下图描述了实体执行的流程。

scheduler_sequence.png

图:实体执行序列

如图序图所示,调度器通过 nvidia::gxf::System::runAsync\_abi() 接口开始执行图实体,并持续此过程直到满足特定结束条件。单个实体可以有多个代码let。这些代码let按照它们在实体中定义的相同顺序执行。任何单个代码let执行失败都会停止所有实体的执行。当任何一个实体的调度项达到 NEVER 状态时,实体自然会从执行中取消调度。

调度项是用于定义实体执行就绪状态的组件。一个实体可以关联多个调度项,每个调度项使用 SchedulingCondition 表示实体的状态。

下表显示了使用 nvidia::gxf::SchedulingCondition 描述的 nvidia::gxf::SchedulingConditionType 的各种状态。

SchedulingConditionType

描述

NEVER 实体将永远不再执行
READY 实体已准备好执行
WAIT 实体将来可能会执行
WAIT_TIME 实体将在指定持续时间后准备好执行
WAIT_EVENT 实体正在等待具有未知时间间隔的异步事件

调度器将死锁定义为当没有实体处于 READYWAIT\_TIMEWAIT\_EVENT 状态时的情况,这些状态保证将来某个时间点执行。这意味着所有实体都处于 WAIT 状态,调度器不知道它们是否会在将来达到 READY 状态。可以配置调度器,使其在使用 stop\_on\_deadlock 参数达到这种状态时停止,否则将轮询实体以检查它们中的任何一个是否已达到 READY 状态。max\_duration 配置参数可用于在指定的时间量过去后停止所有实体的执行,而与其状态无关。

GXF 目前支持两种类型的调度器

  1. 贪婪调度器

  2. 多线程调度器

这是一个基本的单线程调度器,它贪婪地测试调度项。它非常适合简单的用例和可预测的执行,但可能会产生大量的调度项执行开销,使其不适合大型应用程序。调度器需要一个时钟来跟踪时间。根据时钟的选择,调度器的执行方式会有所不同。如果使用实时时钟,调度器将实时执行。这意味着暂停执行——睡眠线程——直到周期性调度项再次到期。如果使用手动时钟,调度将“时间压缩”地发生。这意味着时间流被改变为立即连续执行代码let。

GreedyScheduler 维护处于 READYWAIT\_TIMEWAIT\_EVENT 状态的实体的运行计数。以下活动图描述了贪婪调度器调度实体的决策要点

greedy_scheduler.png

图:贪婪调度器活动图

贪婪调度器配置

贪婪调度器从配置文件中获取以下参数

参数名称

描述

clock 调度器用于定义时间流的时钟。典型的选择是 RealtimeClock 或 ManualClock
max_duration_ms 调度器将执行的最长持续时间(以毫秒为单位)。如果未指定,调度器将运行直到完成所有工作。如果存在周期性项,则意味着应用程序将无限期运行
stop_on_deadlock 如果禁用 stop_on_deadlock,则 GreedyScheduler 会不断轮询所有等待实体的状态,以检查它们中的任何一个是否已准备好执行。

示例用法 – 以下代码片段配置了一个指定了 ManualClock 选项的贪婪调度器。

复制
已复制!
            

name: scheduler components: - type: nvidia::gxf::GreedyScheduler parameters: max_duration_ms: 3000 clock: misc/clock stop_on_deadlock: true --- name: misc components: - name: clock type: nvidia::gxf::ManualClock

多线程调度器更适合具有复杂执行模式的大型应用程序。调度器由一个调度器线程组成,该线程检查实体的状态,并将其分派到负责执行它们的工作线程池。工作线程在执行完成后将实体重新排队到分派队列中。可以使用 worker\_thread\_number 参数配置工作线程的数量。多线程调度器还管理一个专用的队列和线程来处理异步事件。以下活动图演示了多线程调度器实现的要点。

multithread_scheduler.png

图:多线程调度器活动图

如图所示,当实体达到 WAIT\_EVENT 状态时,它会被移动到一个队列中,在其中等待接收事件完成通知。异步事件处理程序线程负责在接收到事件完成通知后将实体移动到调度器。调度器线程还维护处于 READYWAIT\_EVENTWAIT\_TIME 状态的实体数量的运行计数,并使用这些统计信息来检查调度器是否已达到死锁。调度器还需要一个时钟组件来跟踪时间,它使用 clock 参数进行配置。

与贪婪调度器相比,多线程调度器更具资源效率,并且不会因不断轮询调度项的状态而产生任何额外的开销。check\_recession\_period\_ms 参数可用于配置调度器必须等待轮询处于 WAIT 状态的实体状态的时间间隔。

多线程调度器配置

多线程调度器从配置文件中获取以下参数

参数名称

描述

clock 调度器用于定义时间流的时钟。典型的选择是 RealtimeClock 或 ManualClock。
max_duration_ms 调度器将执行的最长持续时间(以毫秒为单位)。如果未指定,调度器将运行直到完成所有工作。如果存在周期性项,则意味着应用程序将无限期运行。
check_recess_period_ms 再次检查实体条件之前要休眠的持续时间 [ms]。这是当实体尚未准备好运行时,调度器将等待的最长持续时间。
stop_on_deadlock 如果启用,当所有实体都处于等待状态,但没有周期性实体来打破僵局时,调度器将停止。当调度条件可以由外部参与者更改时,应禁用此功能,例如手动清除队列。
worker_thread_number 线程数。

示例用法 – 以下代码片段配置了一个指定了工作线程数和最大持续时间的多线程调度器

复制
已复制!
            

name: scheduler components: - type: nvidia::gxf::MultiThreadScheduler parameters: max_duration_ms: 5000 clock: misc/clock worker_thread_number: 5 check_recession_period_ms: 3 stop_on_deadlock: false --- name: misc components: - name: clock type: nvidia::gxf::RealtimeClock

Epoch 调度器用于在外部管理的线程中运行负载。每次运行称为一个 Epoch。调度器遍历所有已知处于活动状态的实体,并逐个执行它们。如果提供了 epoch 预算(以毫秒为单位),它将继续运行所有代码let,直到预算耗尽或没有代码let准备就绪。它可能会超出预算,因为它保证覆盖一个 epoch 中的所有代码let。如果未提供预算,它将遍历所有代码let 一次,并且仅执行一次。

Epoch 调度器从配置文件中获取以下参数

参数名称

描述

clock 调度器用于定义时间流的时钟。典型的选择是 RealtimeClock。

示例用法 – 以下代码片段配置了一个 Epoch 调度器

复制
已复制!
            

name: scheduler components: - name: clock type: nvidia::gxf::RealtimeClock - name: epoch type: nvidia::gxf::EpochScheduler parameters: clock: clock

请注意,Epoch 调度器旨在从外部线程运行。runEpoch(float budget_ms); 可用于设置 budget_ms 并从外部线程运行调度器。如果指定的预算不是正数,则所有节点都将执行一次。

SchedulingTerm 定义了一个特定条件,实体使用该条件来通知调度器它何时准备好执行。GXF 目前支持各种调度项。

PeriodicSchedulingTerm

nvidia::gxf::PeriodicSchedulingTerm 关联的实体在以其 recess\_period 参数指定的周期性时间间隔后准备好执行。PeriodicSchedulingTerm 可以处于 READYWAIT\_TIME 状态。

示例用法

复制
已复制!
            

- name: scheduling_term type: nvidia::gxf::PeriodicSchedulingTerm parameters: recess_period: 50000000

CountSchedulingTerm

nvidia::gxf::CountSchedulingTerm 关联的实体将执行指定的次数,次数由其 count 参数指定。CountSchedulingTerm 可以处于 READYNEVER 状态。当实体已执行 count 次时,调度项达到 NEVER 状态。

示例用法

复制
已复制!
            

- name: scheduling_term type: nvidia::gxf::CountSchedulingTerm parameters: count: 42

MessageAvailableSchedulingTerm

当关联的接收器队列至少具有一定数量的元素时,与 nvidia::gxf::MessageAvailableSchedulingTerm 关联的实体将被执行。接收器使用调度项的 receiver 参数指定。允许实体执行的最小消息数由 min_size 指定。此调度项的可选参数是 front_stage_max_size,即前台最大消息计数。如果设置了此参数,则仅当队列中的消息数不超过此计数时,调度项才允许执行。它可用于不消耗队列中所有消息的代码let。

在下面显示的示例中,队列的最小大小配置为 4。这意味着实体在队列中至少有 4 条消息之前不会执行。

复制
已复制!
            

- type: nvidia::gxf::MessageAvailableSchedulingTerm parameters: receiver: tensors min_size: 4

MultiMessageAvailableSchedulingTerm

当提供的输入接收器列表组合起来至少具有给定数量的消息时,与 nvidia::gxf::MultiMessageAvailableSchedulingTerm 关联的实体将被执行。receivers 参数用于指定输入通道/接收器列表。允许实体执行所需的最小消息数由 min_size 参数设置。

考虑下面显示的示例。当所有三个接收器的组合消息数至少为 min_size 时;即 5,关联的实体将被执行。

复制
已复制!
            

- name: input_1 type: nvidia::gxf::test::MockReceiver parameters: max_capacity: 10 - name: input_2 type: nvidia::gxf::test::MockReceiver parameters: max_capacity: 10 - name: input_3 type: nvidia::gxf::test::MockReceiver parameters: max_capacity: 10 - type: nvidia::gxf::MultiMessageAvailableSchedulingTerm parameters: receivers: [input_1, input_2, input_3] min_size: 5

BooleanSchedulingTerm

当其内部状态设置为 tick 时,与 nvidia::gxf::BooleanSchedulingTerm 关联的实体将被执行。参数 enable_tick 用于控制实体执行。调度项还具有两个 API enable_tick()disable_tick() 来切换其内部状态。可以通过调用这些 API 来控制实体执行。如果 enable_tick 设置为 false,则实体不会执行(调度条件设置为 NEVER)。如果 enable_tick 设置为 true,则实体将执行(调度条件设置为 READY)。实体可以通过维护调度项的句柄来切换其状态。

示例用法

复制
已复制!
            

- type: nvidia::gxf::BooleanSchedulingTerm parameters: enable_tick: true

AsynchronousSchedulingTerm

AsynchronousSchedulingTerm 主要与处理异步事件的实体关联,这些异步事件发生在调度器执行的常规执行之外。由于这些事件本质上是非周期性的,因此 AsynchronousSchedulingTerm 可防止调度器定期轮询实体的状态并降低 CPU 利用率。AsynchronousSchedulingTerm 可以根据它正在等待的异步事件处于 READYWAITWAIT\_EVENTNEVER 状态。

异步事件的状态使用 nvidia::gxf::AsynchronousEventState 描述,并使用 setEventState API 更新。

AsynchronousEventState

描述

READY 初始状态,第一个 tick 待处理
WAIT 异步服务请求尚未发送,无事可做,只能等待
EVENT_WAITING 已向异步服务发送请求,等待事件完成通知
EVENT_DONE 已收到事件完成通知,实体已准备好被 tick
EVENT_NEVER 实体不想再次被 tick,执行结束

与此调度项关联的实体很可能有一个异步线程,该线程可以在 GXF 调度器执行的常规执行周期之外更新调度项的状态。当调度项处于 WAIT 状态时,调度器会定期轮询实体的状态。当调度项处于 EVENT\_WAITING 状态时,调度器将不再检查实体的状态,直到它们收到事件通知,该通知可以使用 GxfEntityEventNotify API 触发。将调度项的状态设置为 EVENT\_DONE 会自动将此通知发送给调度器。实体可以使用 EVENT\_NEVER 状态来指示其执行周期的结束。

示例用法

复制
已复制!
            

- name: async_scheduling_term type: nvidia::gxf::AsynchronousSchedulingTerm

DownsteamReceptiveSchedulingTerm

此调度项指定,如果给定发射器的接收器可以接受新消息,则应执行实体。

示例用法

复制
已复制!
            

- name: downstream_st type: nvidia::gxf::DownstreamReceptiveSchedulingTerm parameters: transmitter: output min_size: 1

TargetTimeSchedulingTerm

此调度项允许在用户指定的时间戳执行。时间戳在提供的时钟上指定。

示例用法

复制
已复制!
            

- name: target_st type: nvidia::gxf::TargetTimeSchedulingTerm parameters: clock: clock/manual_clock

ExpiringMessageAvailableSchedulingTerm

此调度等待接收器中指定数量的消息。当队列中接收到的第一条消息即将过期或队列中有足够的消息时,实体将被执行。receiver 参数用于设置要监视的接收器。参数 max_batch_sizemax_delay_ns 分别指示要批量处理的最大消息数以及从第一条消息开始等待到执行实体的最大延迟。

在下面显示的示例中,当队列中的消息数大于 max_batch_size(即 5)时,或者当从第一条消息到当前时间的延迟大于 max_delay_ns(即 10000000)时,关联的实体将被执行。

复制
已复制!
            

- name: target_st type: nvidia::gxf::ExpiringMessageAvailableSchedulingTerm parameters: receiver: signal max_batch_size: 5 max_delay_ns: 10000000 clock: misc/clock

AND 组合

一个实体可以与多个调度项关联,这些调度项定义其执行行为。调度项是 AND 组合的,以描述实体的当前状态。为了使实体被调度器执行,所有调度项都必须处于 READY 状态,相反,当任何一个调度项达到 NEVER 状态时,实体将从执行中取消调度。AND 组合期间各种状态的优先级顺序为 NEVERWAIT\_EVENTWAITWAIT\_TIMEREADY

示例用法

复制
已复制!
            

components: - name: integers type: nvidia::gxf::DoubleBufferTransmitter - name: fibonacci type: nvidia::gxf::DoubleBufferTransmitter - type: nvidia::gxf::CountSchedulingTerm parameters: count: 100 - type: nvidia::gxf::DownstreamReceptiveSchedulingTerm parameters: transmitter: integers min_size: 1

BTSchedulingTerm

BT(行为树)调度项用于调度行为树实体本身及其在行为树中的子实体(如果有)。

示例用法

复制
已复制!
            

name: root components: - name: root_controller type: nvidia::gxf::EntityCountFailureRepeatController parameters: max_repeat_count: 0 - name: root_st type: nvidia::gxf::BTSchedulingTerm parameters: is_root: true - name: root_codelet type: nvidia::gxf::SequenceBehavior parameters: children: [ child1/child1_st ] s_term: root_st controller: root_controller

上一个 图规范时间戳
下一个 行为树
© 版权所有 2022-2024, NVIDIA。 上次更新于 2025 年 1 月 27 日。