调度程序

调度程序

CAF 运行在本地映射N个参与者(actors)到M个线程.应用程序把任务分解成多个独立的步骤把多个参与者.这样按顺序执行在同一个参与者中相比总的运行时间,和更有效地利用多核的处理器.

拆分任务意味着每个参与者常常短时间的运行.给每个参与者分配单独的线程将会低效.因此,CAF包含一个调度程序动态的分配参与者到工作线程池中.参与者相当于轻量级的状态机.每当一个waiting状态下的参与者接收一个消息,状态会改为ready并且被调度程序执行.CAF无法中断正在运行的参与者,因为参与者是由用户来实现.因此当参与者调用会阻塞的函数比如系统的I/O函数会阻塞当前工作线程和会造成线程繁忙.这样”不合作”的参与者可能通过使用detached参数的swawn option, e.g., system.spawn<detached>(my_actor_fun).

基于参与者模式的应用程序的性能取决与使用的调度算法和它们的配置.不同的应用程序需要不同的权衡.比如,交互式的应用程序比如说GUI或命令行需要实时响庆客户的输入,当一堆任务需要处理而只有一个任务被执行在很短的时间内.

抛开管理参与者来说, 调度程序连接参与者和百参与者之间的代码.为此调度程序区分外部的和内部的事件.一件外部的事件发生在每当从一个非参与者上下文中产生一个参与者或一个参与者从一个不在调度程序控制下的线程接收消息.内部的事件是从高度程序中发送和产生操作.

策略

一个调度程序与一个协调者和一些工作者组成.协调者通过公用的API连接参与者和非参与者环境.但不是必要作为一个代码实体.

CAF的调度程序是一个基于策略设计的完全可定制.下面的概念类显示所有需要的成员类型和成员函数.一个策略是提供两个添加附加的数据成员到协调者和它们各自的工作者的数据结构,比如…工作队列.coordinator_dataworker_data.这个帮助开发者全全控制调度程序的状态.

struct scheduler_policy {
  struct coordinator_data;
  struct worker_data;
  void central_enqueue(Coordinator* self, resumable* job);
  void external_enqueue(Worker* self, resumable* job);
  void internal_enqueue(Worker* self, resumable* job);
  void resume_job_later(Worker* self, resumable* job);
  resumable* dequeue(Worker* self);
  void before_resume(Worker* self, resumable* job);
  void after_resume(Worker* self, resumable* job);
  void after_completion(Worker* self, resumable* job);
};

每当一个新的工作项目被安排 - 通常是发送一个消息到空闲的参与者, central_enqueue, external_enqueueinternal_enqueue中的一个函数被调用.第一个函数被调用当非参与者代码与参与者系统交互时,比如从mainspawning一个参与者.它的第一个参数是一个指向一个协调者的单例而第二个参数为新的工作项目-通常是一个参与者变成ready状态.external_enqueue不会被CAF直接调用.它的模式把一个工作者的任务传递 到另一个工作者中.它的第一个参数接收新任务的工作者,任务是它的第二个参数.第三个函数, internal_enqueue, 当一个参与者与别一个参与者通讯时被调用.第一个参数是当前瞻的工作者,第二个参数是新的工作项目.

工作窃取

CAF默认策略是工作窃取.算法的关键思想是移除边界检查, 全局对列.原算法由Blumofe et al in 1994.调度程序有P个处理器就是P个工作者.

enter image description here

每个工作者从独立的队列中取出工作项目,直到没有工作可取.一旦出现这种情况, 工作者会变成thif.它将选择其它的工作者-通常是随机的-作为victim并且尝试窃取一个工作任务.一个重要的概念,任务(参与者)默认限制在工作者和只有在被窃取才会迁移.这个策略最小化通讯在线程之前和最大化缓存位置.工作窃取有很多算法框架可以选择,比如Java’s Fork-Join (which is used by Akka), Intel’s Threading Building Blocks, several OpenMP implementations, etc.

CAF使用双端队列为它们的工作者,也就是使用两个自旋锁.一个工作窃取模式的缺点是工作者的空闲状态难以检测.当前只有一个工作者或者全部都没有任务可作?因为每个工作者只能知道自己的情况,它不能决定是否要暂停自己或者当新的任务到来的时候回复自己.因此,CAF使用三个策略当工作者执行完工作队列中的任务时尝试窃取其它工作者的任务,首先,它使用积极的轮询间隔,在一个预先定义的数字失败后使用温和的间隔.然后另一个预调的数字失败后,使用松散的间隔.

默认, 积极的策略执行尝试100窃取没有间隔,温和策略尝试500资窃取50微秒间隔时间.最后松散*的策略无期限的运行,每10毫秒尝试一次窃取.可以在一开时配置来覆盖系统的默认设置.

Work Sharing

工作共享

工作共享是CAF中另一个可供选择的策略,使用单个,合局的工作队列.这个策略全用一个mutex和条件变量在总控的队列中.因此这个策略只支持有限的并发但不需要轮询.使用这个策略可以适配低端的设备当能源消耗是一个重要的需求时.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值