进程唤醒时,应该去哪个cpu?

发表于 3年以前  | 总阅读数:343 次

一个睡眠中的进程被唤醒后,应该去哪个cpu上去执行呢?

为方便称呼,执行唤醒流程的进程是waker,被唤醒进程是wakee。

  • waker所在的cpu,waker与wakee可能具有某种程度的亲和性;
  • wakee上次执行的cpu,也许cache上的数据还是hot的;
  • 同理,与waker所在cpu或者wakee上次执行的cpu共享cache的cpu也有很高的选择优先级;
  • 处于负载均衡考虑,放在某个idle的cpu上会更高效利用系统资源;
  • 处于功耗考虑,选择一个cpu使得耗能最少。

显而易见,选择cpu是一个非常复杂的问题。

我们从try_to_wake_up-->select_task_rq此条路径出发,简单了解一下睡眠进程被唤醒过程中的选核思路。

select_task_rq函数会选择wakee的调度类中定义的select_task_rq去执行。

这里以CFS中定义的select_task_rq_fair函数为例进行分析。

先看函数开始部分:

static int
 select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_flags)
 {
 struct sched_domain *tmp, *sd = NULL;
 int cpu = smp_processor_id();
 int new_cpu = prev_cpu;
 int want_affine = 0;
 int sync = (wake_flags & WF_SYNC) && !(current->flags & PF_EXITING);

cpuwaker现在执行的cpu;

new_cpu以及prev_cpuwakee上次执行的cpu;

want_affine用于表示是否满足亲和条件,在后续判断(如果满足亲和条件,则将进程唤醒到waker现在执行的cpu上也是一个比较优的选择);

sync是用来表示wakerwakee之间的关系的。

我们认为waker与wakee之间有两种关系:sync,以及non-sync。

sync——waker在唤醒wakee的时候知道自己很快进入睡眠状态,故最好不要进行抢占。

non-sync——没有同步关系,唤醒的时候,可以尝试触发一次调度。

在这里,sync本质上是放宽了对waker的cpu的idle的判断条件。

接着分析:

 if (sd_flag & SD_BALANCE_WAKE) {
 record_wakee(p);

 if (sched_energy_enabled()) {
 new_cpu = find_energy_efficient_cpu(p, prev_cpu);
 if (new_cpu >= 0)
 return new_cpu;
 new_cpu = prev_cpu;
 }

 want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, p->cpus_ptr);
 }

进程唤醒可以视为一次主动的BALANCE。

record_wakee主要用于更新wakerwakee_flips,用于后续的判断。

 static void record_wakee(struct task_struct *p)
 {
 /*
  * Only decay a single time; tasks that have less then 1 wakeup per
  * jiffy will not have built up many flips.
  */
 if (time_after(jiffies, current->wakee_flip_decay_ts + HZ)) {
 current->wakee_flips >>= 1;
 current->wakee_flip_decay_ts = jiffies;
 }

 if (current->last_wakee != p) {
 current->last_wakee = p;
 current->wakee_flips++;
 }
 }

task_struct中有三个成员:

wakee_flips_decay_ts表示上次进行衰减的时刻;

last_wakee为上次由它唤醒的进程;

wakee_flips度量由它唤醒进程的数量,wakee_flips一秒之前的计数全部除以2,有点衰减的那味儿了。

sched_energy_enabled分支的部分,与功耗EAS调度器有关,暂不分析。

可以明确的是,find_energy_efficient_cpu用于在开启功耗模型下寻找功耗最低的cpu去执行。

wake_wide函数检测waker/wakee是否符合wake_affine模型。(最终用want_affine表示)

wake_wide支持以及waker所在的cpu可以执行wakee时,want_affine生效。

符合wake_affine模型则优先去waker现在执行以及wakee上次执行的cpus中进行选择(放宽对waker执行cpu的条件,最后从二者中挑选一个target cpu)。

static int wake_wide(struct task_struct *p)
 {
 unsigned int master = current->wakee_flips;
 unsigned int slave = p->wakee_flips;
 int factor = __this_cpu_read(sd_llc_size);

 if (master < slave)
 swap(master, slave);
 if (slave < factor || master < slave * factor)
 return 0;
 return 1;
 }

sd_llc_domain为当前sched_domain中能够共享cache的CPU数目;

wakerwakeewakee_flips中较大的称为master,较小的称为slave

当较小的wakee_flips或者较大的wakee_flips与较小的wakee_flips的比值小于sd_llc_size是可以作为wake_affine生效的一部分判断依据。

继续看select_task_rq_fair函数:

 rcu_read_lock();
 for_each_domain(cpu, tmp) {
 /*
  * If both 'cpu' and 'prev_cpu' are part of this domain,
  * cpu is a valid SD_WAKE_AFFINE target.
  */
 if (want_affine && (tmp->flags & SD_WAKE_AFFINE) &&
     cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) {
 if (cpu != prev_cpu)
 new_cpu = wake_affine(tmp, p, cpu, prev_cpu, sync);

 sd = NULL; /* Prefer wake_affine over balance flags */
 break;
 }

 if (tmp->flags & sd_flag)
 sd = tmp;
 else if (!want_affine)
 break;
 }

waker执行的cpu调度域逐步向上,进行如下判断:

want_affine成立,并且调度域满足亲和性条件,并且waker的cpu与wakee上次执行cpu在同一调度域中时,sd为NULL。

如果条件均不满足,则sd置为最后满足sd_flag的调度域。

如果满足want_affine,退出。

在满足第1个条件,且waker执行的cpu与wakee上次执行cpu不相等的情况下,执行wake_affine进行选择。

wake_affine本质上是在waker现在执行的cpu以及wakee上次执行的cpu进行对比,决定要不要给waker现在执行的cpu一点机会。

static int wake_affine(struct sched_domain *sd, struct task_struct *p,
        int this_cpu, int prev_cpu, int sync)
 {
 int target = nr_cpumask_bits;

 if (sched_feat(WA_IDLE))
 target = wake_affine_idle(this_cpu, prev_cpu, sync);

 if (sched_feat(WA_WEIGHT) && target == nr_cpumask_bits)
 target = wake_affine_weight(sd, p, this_cpu, prev_cpu, sync);

 schedstat_inc(p->se.statistics.nr_wakeups_affine_attempts);
 if (target == nr_cpumask_bits)
 return prev_cpu;

 schedstat_inc(sd->ttwu_move_affine);
 schedstat_inc(p->se.statistics.nr_wakeups_affine);
 return target;
 }

首先,如果waker执行的cpu(此时waker为idle,中断唤醒wakee)为空闲或者很快进入空闲态或者wakee上次执行的cpu为空闲,则通过wake_affine_idle可以找到一个合适的target cpu。

 static int
 wake_affine_idle(int this_cpu, int prev_cpu, int sync)
 {
 if (available_idle_cpu(this_cpu) && cpus_share_cache(this_cpu, prev_cpu))
 return available_idle_cpu(prev_cpu) ? prev_cpu : this_cpu;

 if (sync && cpu_rq(this_cpu)->nr_running == 1)
 return this_cpu;

 return nr_cpumask_bits;
 }

如果waker的cpu空闲(中断唤醒)并且waker执行的cpu与wakee上次执行的cpu共享cache时:

wakee上次执行的cpu也空闲,那么回到上次执行的cpu,否则是waker的cpu。

否则sync为1(表示waker很快要退出)并且只有一个进程在执行,那么返回waker执行的cpu。

如果在wake_affine_idle中没有找到target cpu,则进入wake_affine_weight中继续寻找。

 static int
 wake_affine_weight(struct sched_domain *sd, struct task_struct *p,
    int this_cpu, int prev_cpu, int sync)
 {
 s64 this_eff_load, prev_eff_load;
 unsigned long task_load;

 this_eff_load = cpu_load(cpu_rq(this_cpu));

 if (sync) {
 unsigned long current_load = task_h_load(current);

 if (current_load > this_eff_load)
 return this_cpu;

 this_eff_load -= current_load;
 }

 task_load = task_h_load(p);

 this_eff_load += task_load;
 if (sched_feat(WA_BIAS))
 this_eff_load *= 100;
 this_eff_load *= capacity_of(prev_cpu);

 prev_eff_load = cpu_load(cpu_rq(prev_cpu));
 prev_eff_load -= task_load;
 if (sched_feat(WA_BIAS))
 prev_eff_load *= 100 + (sd->imbalance_pct - 100) / 2;
 prev_eff_load *= capacity_of(this_cpu);

 if (sync)
 prev_eff_load += 1;

 return this_eff_load < prev_eff_load ? this_cpu : nr_cpumask_bits;
 }
  1. 计算waker的负载以及cpu负载,在waker即将执行完成的情况下,cpu负载减去进程负载;
  2. waker的cpu负载加上wakee的进程负载
  3. wakee的cpu负载减去wakee的进程负载(此处是假设进程从上次执行的cpu迁移到waker执行的cpu)

最终,哪个cpu负载小,最后return哪个cpu。

如果sd不为空,则进入find_idlest_cpu这条慢速路径。

否则,进入select_idle_sibling快速路径。

 if (unlikely(sd)) {
 /* Slow path */
 new_cpu = find_idlest_cpu(sd, p, cpu, prev_cpu, sd_flag);
 } else if (sd_flag & SD_BALANCE_WAKE) { /* XXX always ? */
 /* Fast path */

 new_cpu = select_idle_sibling(p, prev_cpu, new_cpu);

 if (want_affine)
 current->recent_used_cpu = cpu;
 }
 rcu_read_unlock();

 return new_cpu;
 }

find_idlest_cpu为SMP负载均衡的常用函数,即选择负载最小的cpu去执行。

select_idle_sibling在之前挑选出来的target cpu与上一次执行的cpu(有可能taget与上一次执行是一个cpu)共享cache的调度域中,根据负载选择一个最合适的cpu去执行。

总结

cpu的选择,主要有以下关键点(满足SD_BALANCE_WAKE):

  • find_energy_efficient_cpu,在EAS调度器开启下启用,选择功耗最小的cpu;
  • 如果未开启EAS调度器,首先判断是否根据wake_wide(依据唤醒进程的强度)以及进程可执行的cpu掩码决定满足waker执行cpu的亲和性;
  • 如果满足亲和性,会通过wake_affine来判断要不要给唤醒wakee的cpu一点执行进程的机会;
  • 不满足亲和性或者调度域不支持情况下,会走到find_idlest_cpu(慢速路径),进行负载均衡的选择;
  • 否则,进入快速路径,通过select_idle_sibling,在wake_affine挑选出来的target cpu以及上一次执行的cpu共享cache的调度域中,根据负载选择一个cpu进行执行。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/e5L82fcuQ0XhEhvTcxtXuw

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237229次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8063次阅读
 目录