当前位置: 首页 > article >正文

windows C++-计划组

本文档介绍并发运行时中计划组的角色。 计划组将相关任务关联在一起或进行分组。 每个计划程序都有一个或多个计划组。 当你需要在任务之间处于较高位置时(例如,当一组相关的任务受益于在相同的处理器节点上执行操作时),可使用计划组。 相反,当应用程序具有特定质量要求时,例如,当希望限制分配给一组任务的处理资源量时,请使用计划程序实例。 有关计划程序实例的详细信息,请参阅计划程序实例。

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

每个 Scheduler 对象对于每个计划节点都有一个默认的计划组。 计划节点映射到基础系统拓扑。 运行时为每个处理器包或非统一内存体系结构 (NUMA) 节点创建一个计划节点,以较大的数为准。 如果不显式将任务与计划组关联,计划程序将选择要向其添加任务的组。

SchedulingProtocol 计划程序策略会影响计划程序在每个计划组中执行任务的顺序。 当 SchedulingProtocol 设置为 EnhanceScheduleGroupLocality(默认值)时,任务计划程序将在当前任务完成或以协作方式暂停时从它正在处理的计划组中选择下一个任务。 任务计划程序会在移动到下一个可用组之前搜索当前计划组的工作。 相反,当 SchedulingProtocol 设置为 EnhanceForwardProgress 时,计划程序会在每个任务完成或暂停后移动到下一个计划组。 有关比较这些策略的示例,请参阅如何:使用计划组影响执行顺序。

运行时使用 concurrency::ScheduleGroup 类表示计划组。 若要创建 ScheduleGroup 对象,请调用 concurrency::CurrentScheduler::CreateScheduleGroup 或 concurrency::Scheduler::CreateScheduleGroup 方法。 运行时使用引用计数机制来控制 ScheduleGroup 对象的生存期,就像对 Scheduler 对象所做的那样。 创建 ScheduleGroup 对象时,运行时会将引用计数器设置为 1。 concurrency::ScheduleGroup::Reference 方法将引用计数器递增 1。 concurrency::ScheduleGroup::Release 方法将引用计数器递减 1。

并发运行时中的许多类型允许将对象与计划组关联。 例如,concurrency::agent 类和消息块类(如 concurrency::unbounded_buffer、concurrency::join 和 concurrency::timer)可提供采用 ScheduleGroup 对象的构造函数的重载版本。 运行时使用与此 ScheduleGroup 对象关联的 Scheduler 对象来计划任务。

还可以使用 concurrency::ScheduleGroup::ScheduleTask 方法来计划轻量级任务。

使用计划组影响执行顺序

在并发运行时,计划任务的顺序是不确定的。 但是,可以使用计划策略来影响任务运行的顺序。 本主题说明如何将计划组与 concurrency::SchedulingProtocol 计划程序策略结合使用,以影响任务运行的顺序。

此示例运行一组任务两次,每次都使用不同的计划策略。 这两种策略都将处理资源的最大数量限制为 2。 第一次运行使用默认的 EnhanceScheduleGroupLocality 策略,第二次运行使用 EnhanceForwardProgress 策略。 在 EnhanceScheduleGroupLocality 策略中,计划程序在一个计划组中运行所有任务,直到每个任务完成或生成结果。 在 EnhanceForwardProgress 策略中,计划程序在一个任务完成或生成结果后,以轮循机制移至下一个计划组。

当每个计划组包含相关任务时,EnhanceScheduleGroupLocality 策略通常会提高性能,因为在任务之间保留了缓存区域。 EnhanceForwardProgress 策略使任务能够向前推进,当你需要跨计划组公平计划时非常有用。

示例

此示例定义派生自 concurrency::agent 的 work_yield_agent 类。 work_yield_agent 类执行一个工作单元,生成当前上下文,然后执行另一个工作单元。 代理使用 concurrency::wait 函数协同生成当前上下文,以便其他上下文可以运行。

此示例创建四个 work_yield_agent 对象。 为了说明如何设置计划程序策略以影响代理运行的顺序,此示例将前两个代理与一个计划组相关联,将另外两个代理与另一个计划组相关联。 此示例使用 concurrency::CurrentScheduler::CreateScheduleGroup 方法创建 concurrency::ScheduleGroup 对象。 此示例运行所有四个代理两次,每次都使用不同的计划策略。

// scheduling-protocol.cpp
// compile with: /EHsc
#include <agents.h>
#include <vector>
#include <algorithm>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

#pragma optimize( "", off )
// Simulates work by performing a long spin loop.
void spin_loop()
{
   for (int i = 0; i < 500000000; ++i)
   {
   }
}
#pragma optimize( "", on )

// Agent that performs some work and then yields the current context.
class work_yield_agent : public agent
{
public:
   explicit work_yield_agent(
      unsigned int group_number, unsigned int task_number)
      : _group_number(group_number)
      , _task_number(task_number)
   {
   }

   explicit work_yield_agent(Scheduler& scheduler,
      unsigned int group_number, unsigned int task_number)
      : agent(scheduler)
      , _group_number(group_number)
      , _task_number(task_number)
   {
   }

   explicit work_yield_agent(ScheduleGroup& group,
      unsigned int group_number, unsigned int task_number)
      : agent(group)       
      , _group_number(group_number)
      , _task_number(task_number)
   {
   }
   
protected:
   // Performs the work of the agent.   
   void run()
   {
      wstringstream header, ss;

      // Create a string that is prepended to each message.
      header << L"group " << _group_number 
             << L",task " << _task_number << L": ";

      // Perform work.
      ss << header.str() << L"first loop..." << endl;
      wcout << ss.str();
      spin_loop();

      // Cooperatively yield the current context. 
      // The task scheduler will then run all blocked contexts.
      ss = wstringstream();
      ss << header.str() << L"waiting..." << endl;
      wcout << ss.str();
      concurrency::wait(0);

      // Perform more work.
      ss = wstringstream();
      ss << header.str() << L"second loop..." << endl;
      wcout << ss.str();
      spin_loop();

      // Print a final message and then set the agent to the 
      // finished state.
      ss = wstringstream();
      ss << header.str() << L"finished..." << endl;
      wcout << ss.str();

      done();
   }  

private:
   // The group number that the agent belongs to.
   unsigned int _group_number;
   // A task number that is associated with the agent.
   unsigned int _task_number;
};

// Creates and runs several groups of agents. Each group of agents is associated 
// with a different schedule group.
void run_agents()
{
   // The number of schedule groups to create.
   const unsigned int group_count = 2;
   // The number of agent to create per schedule group.
   const unsigned int tasks_per_group = 2;

   // A collection of schedule groups.
   vector<ScheduleGroup*> groups;
   // A collection of agents.
   vector<agent*> agents;

   // Create a series of schedule groups. 
   for (unsigned int group = 0; group < group_count; ++group)
   {
      groups.push_back(CurrentScheduler::CreateScheduleGroup());

      // For each schedule group, create a series of agents.
      for (unsigned int task = 0; task < tasks_per_group; ++task)
      {
         // Add an agent to the collection. Pass the current schedule 
         // group to the work_yield_agent constructor to schedule the agent
         // in this group.
         agents.push_back(new work_yield_agent(*groups.back(), group, task));
      }
   }

   // Start each agent.
   for_each(begin(agents), end(agents), [](agent* a) {
      a->start();
   });

   // Wait for all agents to finsih.
   agent::wait_for_all(agents.size(), &agents[0]);

   // Free the memory that was allocated for each agent.
   for_each(begin(agents), end(agents), [](agent* a) {
      delete a;
   });

   // Release each schedule group.
   for_each(begin(groups), end(groups), [](ScheduleGroup* group) {
      group->Release();
   });
}

int wmain()
{
   // Run the agents two times. Each run uses a scheduler
   // policy that limits the maximum number of processing resources to two.

   // The first run uses the EnhanceScheduleGroupLocality 
   // scheduling protocol. 
   wcout << L"Using EnhanceScheduleGroupLocality..." << endl;
   CurrentScheduler::Create(SchedulerPolicy(3, 
      MinConcurrency, 1,
      MaxConcurrency, 2,
      SchedulingProtocol, EnhanceScheduleGroupLocality));

   run_agents();
   CurrentScheduler::Detach();

   wcout << endl << endl;

   // The second run uses the EnhanceForwardProgress 
   // scheduling protocol. 
   wcout << L"Using EnhanceForwardProgress..." << endl;
   CurrentScheduler::Create(SchedulerPolicy(3, 
      MinConcurrency, 1,
      MaxConcurrency, 2,
      SchedulingProtocol, EnhanceForwardProgress));

   run_agents();
   CurrentScheduler::Detach();
}

本示例生成以下输出。 

Using EnhanceScheduleGroupLocality...
group 0,
    task 0: first loop...
group 0,
    task 1: first loop...
group 0,
    task 0: waiting...
group 1,
    task 0: first loop...
group 0,
    task 1: waiting...
编译代码

复制示例代码,并将它粘贴到 Visual Studio 项目中,或粘贴到名为 scheduling-protocol.cpp 的文件中,再在 Visual Studio 命令提示符窗口中运行以下命令。

cl.exe /EHsc scheduling-protocol.cpp

http://www.kler.cn/a/328315.html

相关文章:

  • 【QT实战】加解密文件夹之————应用程序获取管理员权限
  • 优化 MFC CGridCtrl 的表格布局与功能
  • 柔性仿人手指全覆盖磁皮肤,具备接触觉和运动觉的双模态感知能力
  • 《探索 C++:一门强大且多功能的编程语言》
  • 【c++丨STL】list的使用
  • Java-异步方法@Async+自定义分布式锁注解Redission例子
  • 机器学习西瓜书——线性判别分析LDA
  • 使用PyTorch实现自然语言处理:从基础到实践
  • Go基础学习07-map注意事项;多协程对map的资源竞争;sync.Mutex避免竟态条件
  • QEMU使用Qemu-Guest-Agent传输文件、执行指令等
  • http增删改查四种请求方式操纵数据库
  • k8s 1.28.2 集群部署 ingress 1.11.1 包含 admission-webhook
  • Qt 中的 QListWidget、QTreeWidget 和 QTableWidget:简化的数据展示控件
  • 开发微信小程序 基础03
  • scala 2.12 error: value foreach is not a member of Object
  • 低代码用户中心:构建高效便捷的用户管理平台
  • VUE 开发——AJAX学习(二)
  • 51单片机学习第五课---B站UP主江协科技
  • 【网络安全】消息鉴别
  • 五.海量数据实时分析-FlinkCDC+DorisConnector实现数据的全量增量同步
  • Require:基于雪花算法完成一个局部随机,全局离散没有热点切唯一的数值Id生成器。
  • FileLink跨网文件交换:高效、安全、灵活的企业文件传输新方案
  • 力扣10.1
  • 5QI(5G QoS Identifier)
  • 《Linux从小白到高手》理论篇(二):Linux的目录结构和磁盘管理
  • 基于贝叶斯优化CNN-GRU网络的数据分类识别算法matlab仿真