windows C++ - 任务计划程序(并发运行时)

如果希望微调并发运行时的现有代码的性能,则任务计划程序会很有用。

无法从通用 Windows 平台 (UWP) 应用获取任务计划程序。 
在 Visual Studio 2015 及更高版本中,concurrency::task 类和 ppltasks.h 中的相关类型使用 Windows 线程池作为其计划程序。 本主题不再适用于在 ppltasks.h 中定义的类型。 并行算法(例如 parallel_for)继续使用并发运行时作为默认计划程序。

并发运行时提供了一个默认计划程序,因此无需在应用程序中创建一个。 由于任务计划程序有助于优化应用程序的性能,如果你刚开始接触并发运行时,建议从使用并行模式库 (PPL) 或异步代理库开始。

任务计划程序在运行时计划和协调任务。 任务是指执行特定作业的工作单元。 任务通常可以与其他任务并行运行。 任务组项、并行算法和异步代理所执行的工作都属于任务示例。

任务计划程序可以管理关于在具有多个计算资源的计算机上高效执行计划任务的详细信息。 任务计划程序还使用基础操作系统的最新功能。 因此,使用并发运行时的应用程序会自动缩放,并提高具有扩展功能的硬件性能。

与其他并发模型进行比较介绍了抢先式和协作式计划机制之间的差异。 任务计划程序将操作系统的抢先式计划程序与协作式计划和工作窃取算法配合使用,以达到处理资源的最大使用率。

并发运行时提供了默认计划程序,因此你无需管理基础结构详细信息。 因此,通常不会直接使用任务计划程序。 但是,为了满足应用程序的质量要求,你可以使用任务计划程序提供自己的计划策略或将计划程序与特定任务相关联。 例如,假设你有一个作用范围不超过四个处理器的并行排序例程。 你可以使用计划程序策略来创建可生成不超过四个并发任务的计划程序。 通过在此计划程序上运行排序例程,可使其他活动计划程序使用剩余的任何处理资源。

计划程序实例

下面介绍了并发运行时中计划程序实例的作用,以及如何使用 concurrency::Scheduler 和 concurrency::CurrentScheduler 类创建和管理计划程序实例。 当你希望将显式计划策略与特定类型的工作负载相关联时,计划程序实例非常有用。 例如,你可以创建一个计划程序实例来以提升的线程优先级运行一些任务,并使用默认计划程序以普通线程优先级运行其他任务。

并发运行时提供了一个默认计划程序,因此无需在应用程序中创建一个。 由于任务计划程序有助于优化应用程序的性能,如果你刚开始接触并发运行时,建议从使用并行模式库 (PPL) 或异步代理库开始。

计划程序和 CurrentScheduler 类

任务计划程序使应用程序能够使用一个或多个计划程序实例来计划工作。 concurrency::Scheduler 类表示计划程序实例,并封装与计划任务相关的功能。

附加到计划程序的线程称为执行上下文(或只是上下文)。 在任何时候都可以有一个计划程序在当前上下文中处于活动状态。 活动计划程序也称为“当前计划程序”。 并发运行时使用 concurrency::CurrentScheduler 类提供对当前计划程序的访问。 一个上下文的当前计划程序可能与另一个上下文的当前计划程序不同。 运行时不提供当前计划程序的进程级表示形式。

通常,CurrentScheduler 类用于处理当前计划程序。 当你需要管理一个不是当前计划程序的计划程序时,Scheduler 类非常有用。

创建计划程序实例

创建 Scheduler 对象的方法有三种:

  • 如果不存在计划程序,运行时会在你使用运行时功能(例如并行算法)执行工作时,为你创建默认计划程序。 默认计划程序将成为启动并行工作的上下文的当前计划程序;
  • concurrency::CurrentScheduler::Create 方法将创建一个使用特定策略的 Scheduler 对象,并将该计划程序与当前上下文相关联;
  • concurrency::Scheduler::Create 方法可创建一个使用特定策略的 Scheduler 对象,但不将其与当前上下文相关联;

允许运行时创建默认计划程序后,所有并发任务就可以共享同一计划程序。 通常,并行模式库 (PPL) 或异步代理库提供的功能可用于执行并行工作。 因此,无需直接使用计划程序来控制其策略或生存期。 当你使用 PPL 或代理库时,运行时会创建默认计划程序(如果它不存在),并使它成为每个上下文的当前计划程序。 当你创建计划程序并将其设置为当前计划程序后,运行时会使用该计划程序来计划任务。 只有当你需要特定的计划策略时,才能创建额外的计划程序实例。

管理计划程序实例的生存期

运行时使用引用计数机制来控制 Scheduler 对象的生存期。

当你使用 CurrentScheduler::Create 方法或 Scheduler::Create 方法创建 Scheduler 对象时,运行时将该计划程序的初始引用计数值设置为一。 当你调用 concurrency::Scheduler::Attach 方法时,运行时会递增引用计数值。 Scheduler::Attach 方法将 Scheduler 对象与当前上下文相关联。 这将使它成为当前计划程序。 当你调用 CurrentScheduler::Create 方法时,运行时将创建 Scheduler 对象并将其附加到当前上下文(并将引用计数值设置为一)。 你还可以使用 concurrency::Scheduler::Reference 方法来递增 Scheduler 对象的引用计数值。

当你调用 concurrency::CurrentScheduler::Detach 方法以分离当前计划程序,或者调用 concurrency::Scheduler::Release 方法时,运行时会递减引用计数值。 当引用计数值达到零时,运行时会在所有计划任务完成后销毁 Scheduler 对象。 一个正在运行的任务被允许递增当前计划程序的引用计数值。 因此,如果引用计数值达到零,并且有一个任务递增了引用计数值,则在引用计数值再次达到零且所有任务完成之前,运行时不会销毁 Scheduler 对象。

运行时为每个上下文维护一个 Scheduler 对象的内部堆栈。 当你调用 Scheduler::Attach 或 CurrentScheduler::Create 方法时,运行时会将该 Scheduler 对象推送到当前上下文的堆栈中。 这将使它成为当前计划程序。 当你调用 CurrentScheduler::Detach 时,运行时会从堆栈中弹出当前上下文的当前计划程序,并将上一个计划程序设置为当前计划程序。

运行时提供了几种方式来管理计划程序实例的生存期。 下表显示了针对创建计划程序或将计划程序附加到当前上下文的每个方法从当前上下文中释放或分离计划程序的适当方法。

调用不适当的释放或分离方法会在运行时产生不明确的行为。

当你使用的功能(例如 PPL)导致运行时为你创建默认计划程序时,请不要释放或分离此计划程序。 运行时会管理它所创建的任何计划程序的生存期。

由于在所有任务完成之前,运行时不会销毁 Scheduler 对象,你可以使用 concurrency::Scheduler::RegisterShutdownEvent 方法或 concurrency::CurrentScheduler::RegisterShutdownEvent 方法在 Scheduler 对象被销毁时收到通知。 在你必须等待 Scheduler 对象计划的每个任务完成的情况下,这非常有用。

方法和功能

本部分总结了 CurrentScheduler 和 Scheduler 类的重要方法。

将 CurrentScheduler 类视为创建计划程序以用于当前上下文的帮助程序。 Scheduler 类可以让你控制属于另一个上下文的计划程序。

下表显示了 CurrentScheduler 类定义的重要方法。

下表显示了 Scheduler 类定义的重要方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值