@

【WALT】scale_exec_time() 代码详解

代码版本:Linux4.9 android-msm-crosshatch-4.9-android12

代码展示

static inline u64 scale_exec_time(u64 delta, struct rq *rq)
{
u32 freq;
// ⑴ 将 CPU cycles 转换为 CPU 当前频率
freq = cpu_cycles_to_freq(rq->cc.cycles, rq->cc.time);
// ⑵ 归一化 delta
delta = DIV64_U64_ROUNDUP(delta * freq, max_possible_freq);
delta *= rq->cluster->exec_scale_factor;
delta >>= 10; return delta;
}

代码逻辑:

scale_exec_time() 函数用于给任务的运行时间 delta 进行归一化。

为什么归一化?

EAS 主要针对异构 CPU 架构,如 Arm big.LITTLE,因为这种架构有不同性能和功耗的 CPU 核心,不同 CPU 的最大算力、最大频率等都不同。假定一个任务在当前窗口中运行了 5ms,对不同频率的两个 CPU 来说,5ms 带来的负载是截然不同的。

WALT 算法引入了一种类似权重的方法,根据 CPU 的频率(frequency)和 最大每周期指令数(efficiency)来对任务的运行时间进行归一化。

(注:此处 efficiency 的定义并不确定,在内核文档中出现过这个定义。)

⑴ 将 CPU cycles 转换为 CPU 当前频率

freq = cpu_cycles_to_freq(rq->cc.cycles, rq->cc.time);

static inline u32 cpu_cycles_to_freq(u64 cycles, u64 period)
{
return div64_u64(cycles, period);
}

在这里 freq = rq->cc.cycles / rq->cc.time。其中,rq->cc.cycles 和 rq->cc.time 在函数 update_task_rq_cpu_cycles() 中更新:

static void
update_task_rq_cpu_cycles(struct task_struct *p, struct rq *rq, int event,
u64 wallclock, u64 irqtime)
{
u64 cur_cycles;
int cpu = cpu_of(rq); lockdep_assert_held(&rq->lock); if (!use_cycle_counter) {
rq->cc.cycles = cpu_cur_freq(cpu);
rq->cc.time = 1;
return;
} cur_cycles = read_cycle_counter(cpu, wallclock); /*
* If current task is idle task and irqtime == 0 CPU was
* indeed idle and probably its cycle counter was not
* increasing. We still need estimatied CPU frequency
* for IO wait time accounting. Use the previously
* calculated frequency in such a case.
*/
if (!is_idle_task(rq->curr) || irqtime) {
if (unlikely(cur_cycles < p->cpu_cycles))
rq->cc.cycles = cur_cycles + (U64_MAX - p->cpu_cycles);
else
rq->cc.cycles = cur_cycles - p->cpu_cycles;
rq->cc.cycles = rq->cc.cycles * NSEC_PER_MSEC; if (event == IRQ_UPDATE && is_idle_task(p))
/*
* Time between mark_start of idle task and IRQ handler
* entry time is CPU cycle counter stall period.
* Upon IRQ handler entry sched_account_irqstart()
* replenishes idle task's cpu cycle counter so
* rq->cc.cycles now represents increased cycles during
* IRQ handler rather than time between idle entry and
* IRQ exit. Thus use irqtime as time delta.
*/
rq->cc.time = irqtime;
else
rq->cc.time = wallclock - p->ravg.mark_start;
BUG_ON((s64)rq->cc.time < 0);
} p->cpu_cycles = cur_cycles; trace_sched_get_task_cpu_cycles(cpu, event, rq->cc.cycles, rq->cc.time, p);
}

⑵ 归一化 delta

  1. delta = DIV64_U64_ROUNDUP(delta * freq, max_possible_freq);

    即 delta = delta * freq/max_possible_freq。

    freq 是当前 CPU 的频率,由 ⑴ 计算而得:freq = rq->cc.cycles / rq->cc.time。

    max_possible_freq 就是 max(policy->cpuinfo.max_freq)。

    policy 可以浅显地认为是簇号,如不同的 policy 指向小核簇、大核簇和超大核:

    • 对于拥有多个 CPU 的簇来说,频率的计算在 sugov_update_shared() 中进行,簇内每个 CPU 的频率都是一致的,因此一个簇会拥有一个当前频率和一个最大频率,即 policy->cpuinfo.max_freq;
    • 对于单个 CPU 来说,频率的计算在 sugov_update_single() 中进行,它也会有一个最大频率 policy->cpuinfo.max_freq。

    在运行该版本内核的 pixel 3xl 中,8 个 CPU 分为小核簇与大核簇,他们的最大频率分别是 381 和 1024。

  2. delta *= rq->cluster->exec_scale_factor;

    cluster->exec_scale_factor = 1024 * cluster->efficiency/max_possible_efficiency

    cluster->efficiency 可能指 运行任务的 CPU 的每周期指令数 (IPC)。

    max_possible_efficiency 可能指 系统中任何 CPU 提供的最大 IPC。

    这个值在设备树中给定,在运行该版本内核的 pixel 3xl 中,小核簇和大核簇的 max_possible_efficiency 分别是 1024 和 1740。

  3. delta >>= 10;

    即 delta = delta / 1024。

将三句代码一起看,能得出一个等式:

\(delta\_s = delta\times\dfrac{curr\_freq}{max\_possible\_freq}\times\dfrac{cluster->efficiency}{max\_possible\_efficiency}\)

点击此处回到 WALT 入口函数 update_task_ravg()

【WALT】scale_exec_time() 代码详解的更多相关文章

  1. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  2. ASP.NET MVC 5 学习教程:生成的代码详解

    原文 ASP.NET MVC 5 学习教程:生成的代码详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...

  3. Github-karpathy/char-rnn代码详解

    Github-karpathy/char-rnn代码详解 zoerywzhou@gmail.com http://www.cnblogs.com/swje/ 作者:Zhouwan  2016-1-10 ...

  4. 代码详解:TensorFlow Core带你探索深度神经网络“黑匣子”

    来源商业新知网,原标题:代码详解:TensorFlow Core带你探索深度神经网络“黑匣子” 想学TensorFlow?先从低阶API开始吧~某种程度而言,它能够帮助我们更好地理解Tensorflo ...

  5. JAVA类与类之间的全部关系简述+代码详解

    本文转自: https://blog.csdn.net/wq6ylg08/article/details/81092056类和类之间关系包括了 is a,has a, use a三种关系(1)is a ...

  6. Java中String的intern方法,javap&cfr.jar反编译,javap反编译后二进制指令代码详解,Java8常量池的位置

    一个例子 public class TestString{ public static void main(String[] args){ String a = "a"; Stri ...

  7. Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测

    Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测 2017年12月13日 17:39:11 机器之心V 阅读数:5931   近日,Artur Suilin 等人发布了 Kaggl ...

  8. 基础 | batchnorm原理及代码详解

    https://blog.csdn.net/qq_25737169/article/details/79048516 https://www.cnblogs.com/bonelee/p/8528722 ...

  9. 非极大值抑制(NMS,Non-Maximum Suppression)的原理与代码详解

    1.NMS的原理 NMS(Non-Maximum Suppression)算法本质是搜索局部极大值,抑制非极大值元素.NMS就是需要根据score矩阵和region的坐标信息,从中找到置信度比较高的b ...

  10. 委托与事件代码详解与(Object sender,EventArgs e)详解

    委托与事件代码详解 using System;using System.Collections.Generic;using System.Text; namespace @Delegate //自定义 ...

随机推荐

  1. JavaScript的引入方式

    外部JS文件 deno.js alert('你好!JavaScript'); JS引入方式.html <!--方式一:内部脚本--> <!--标签不能自闭和--> <sc ...

  2. CSS页面布局方式

    css页面布局方式 1.标准流 <!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  3. 尝试CentOS8---部署集群(生产环境7.9为好)

    一.LVS集群简介 什么是集群 通过网络将很多服务器集中起来,提供同一种服务,在客户端看来就像是只有一个服务器 二.LVS-NAT集群 1.环境准备 启动3台虚拟机,禁用selinux和firewal ...

  4. [Pytorch框架] 1.1、Pytorch简介

    文章目录 1.1 Pytorch 简介 1.1.1 PyTorch的由来 1.1.2 Torch是什么? 1.1.3 重新介绍 PyTorch 1.1.4 对比PyTorch和Tensorflow 1 ...

  5. 关于 import 和 import static

    import 嘛,就是导包.比如说java的一些自带的包,例如 import java.lang.Matn: 又或者我们自己做的包,例如 import com.link.testImport; 一些实 ...

  6. Tomcat总体架构,启动流程与处理请求流程

    系列文章目录和关于我 参考书籍<Tomcat架构解析> 一丶Tomcat总体架构 本文沿袭<Tomcat架构解析>中启发式的方式来总结Tomcat总体架构 1 Server S ...

  7. 2022-10-23:给你一个整数数组 nums 。如果 nums 的一个子集中, 所有元素的乘积可以表示为一个或多个 互不相同的质数 的乘积,那么我们称它为 好子集 。 比方说,如果 nums =

    2022-10-23:给你一个整数数组 nums .如果 nums 的一个子集中, 所有元素的乘积可以表示为一个或多个 互不相同的质数 的乘积,那么我们称它为 好子集 . 比方说,如果 nums = ...

  8. 2020-11-10:golang中的接口,类型不空,值为空,如何判断是nil?

    福哥答案2020-11-10: reflect.ValueOf(接口变量).IsNil(),用这个即可判断.对于值类型,会panic.两种方法如下:1.异常判断:recover捕获.2.类型判断:re ...

  9. 2022-05-15:N个学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输。 问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件; 问题2:至

    2022-05-15:N个学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输. 问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件: 问题2:至 ...

  10. 2021-05-12:给定一个数组arr,只能对arr中的一个子数组排序, 但是想让arr整体都有序。返回满足这一设定的子数组中,最短的是多长?

    2021-05-12:给定一个数组arr,只能对arr中的一个子数组排序, 但是想让arr整体都有序.返回满足这一设定的子数组中,最短的是多长? 福大大 答案2021-05-12: 从左往右遍历,缓存 ...