├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── conf.json
├── dataset
├── soc_model
│ ├── README.md
│ ├── model_e7420.json
│ ├── model_e8890.json
│ ├── model_e8895.json
│ ├── model_sdm616.json
│ ├── model_sdm625.json
│ ├── model_sdm626.json
│ ├── model_sdm636.json
│ ├── model_sdm650_652_653.json
│ ├── model_sdm660.json
│ ├── model_sdm820.json
│ ├── model_sdm821_v1.json
│ ├── model_sdm821_v2.json
│ ├── model_sdm821_v3.json
│ ├── model_sdm835.json
│ └── raw
│ │ ├── e7420.xlsx
│ │ ├── e8890.xlsx
│ │ ├── e8895.xlsx
│ │ ├── sd626.xlsx
│ │ ├── sd820.xlsx
│ │ ├── sd821.xlsx
│ │ ├── sd835.xlsx
│ │ ├── sdm616.xlsx
│ │ ├── sdm636.xlsx
│ │ ├── sdm650.xlsx
│ │ └── sdm660.csv
└── workload
│ └── osborn
│ ├── bili-danmu.json
│ ├── bili-download.json
│ ├── bili-feed.json
│ ├── coolapk-feed.json
│ ├── game-7days-city-boss.json
│ ├── game-7days-city-regular.json
│ ├── idle-music.json
│ ├── meituan-explore.json
│ ├── offscreen-merged.json
│ ├── onscreen-merged.json
│ ├── qq-chat.json
│ ├── qq-qzone.json
│ ├── raw
│ ├── README.md
│ └── info.json
│ ├── share-feed.json
│ ├── taobao-international-explore.json
│ ├── task-switch.json
│ ├── tieba-lite.json
│ ├── twitter-feed.json
│ ├── via-iphonexs-intro.json
│ ├── wx-chat.json
│ ├── wx-gongzhonghao.json
│ ├── wx-moment.json
│ ├── wx-select-pic.json
│ └── xianyu-search.json
├── media
└── sim.png
├── source
├── 3rd
│ ├── nlohmann
│ │ └── json.hpp
│ └── openga
│ │ └── openga.hpp
├── main.cpp
├── opt
│ ├── openga_helper.cpp
│ └── openga_helper.h
├── output
│ ├── dump.cpp
│ └── dump.h
├── sim
│ ├── cpumodel.cpp
│ ├── cpumodel.h
│ ├── hmp.h
│ ├── hmp_pelt.cpp
│ ├── hmp_pelt.h
│ ├── hmp_walt.cpp
│ ├── hmp_walt.h
│ ├── input_boost.cpp
│ ├── input_boost.h
│ ├── interactive.cpp
│ ├── interactive.h
│ ├── rank.cpp
│ ├── rank.h
│ ├── sim.hpp
│ ├── sim_types.h
│ ├── workload.cpp
│ └── workload.h
└── utils
│ └── misc.h
├── template
└── powercfg_template.sh
└── tools
├── migrate.py
├── standby_load_20180308_from_171023.csv
└── tracefile_parse.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
34 | # too big ADB systrace, ~600MB
35 | *.html
36 |
37 | # binary
38 | /wipe
39 |
40 | /.vscode
41 | /build
42 | /output
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Project WIPE-v2
2 | # Author: Matt Yang
3 |
4 | CC := gcc
5 | CXX := g++
6 | CFLAGS := -std=c99 -flto
7 | CXXFLAGS := -std=c++11 -flto
8 | LDFLAGS := -Wl,--as-needed -flto
9 |
10 | SRC_DIR := ./source
11 | INC_DIR := ./source
12 | BUILD_DIR := ./build
13 | DEP_DIR := $(BUILD_DIR)/dep
14 |
15 | BIN_NAME := wipe
16 | REL_FLAGS := -O3 -s
17 | REL_DEFINES :=
18 | DBG_FLAGS := -O0 -g -Wall
19 | DBG_DEFINES :=
20 |
21 | EXT_LIB_INC :=
22 | EXT_LIBS :=
23 |
24 | INC := $(shell find $(INC_DIR) -name '*.h')
25 | INC += $(shell find $(INC_DIR) -name '*.hpp')
26 | SRC := $(shell find $(SRC_DIR) -name '*.c')
27 | SRC += $(shell find $(SRC_DIR) -name '*.cpp')
28 |
29 | OBJS := $(foreach f,$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SRC))),$(BUILD_DIR)/$(f))
30 | INCLUDES := $(foreach f,$(sort $(dir $(INC))),-I$(f)) $(EXT_LIB_INC)
31 | LIBS := -lpthread $(EXT_LIBS)
32 |
33 | # 生成.c/cpp对.h的依赖,由include插入到makefile, 不使用冒号用于延后展开 $@ 和 $(*F)
34 | # http://maskray.me/blog/2011-08-11-generate-dependency-in-makefile
35 | DEP_FLAGS = -MM -MP -MT $@ -MF $(DEP_DIR)/$(*F).d
36 |
37 | # gcc并不会自己生成目录
38 | $(shell mkdir -p $(DEP_DIR) > /dev/null)
39 | $(shell mkdir -p $(dir $(OBJS)) > /dev/null)
40 |
41 | .PHONY: all release debug clean help
42 |
43 | all: release
44 |
45 | release: MODE_FLAG = $(REL_FLAGS)
46 | release: DEFINES = $(REL_DEFINES)
47 | release: $(OBJS)
48 | @$(CXX) $(CXXFLAGS) $(INCLUDES) $(LDFLAGS) $(DEFINES) $(MODE_FLAG) -o $(BIN_NAME) $^ $(LIBS)
49 | @echo -e ' bin\t ./$(BIN_NAME)'
50 | @echo -e '\033[32m\033[1m build $@ done. \033[0m'
51 |
52 | debug: MODE_FLAG = $(DBG_FLAGS)
53 | debug: DEFINES = $(DBG_DEFINES)
54 | debug: $(OBJS)
55 | @$(CXX) $(CXXFLAGS) $(INCLUDES) $(LDFLAGS) $(DEFINES) $(MODE_FLAG) -o $(BIN_NAME) $^ $(LIBS)
56 | @echo -e ' bin\t ./$(BIN_NAME)'
57 | @echo -e '\033[32m\033[1m build $@ done. \033[0m'
58 |
59 | $(BUILD_DIR)/%.o: %.c
60 | @echo -e ' cc\t $<'
61 | @$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) $(MODE_FLAG) $(DEP_FLAGS) $<
62 | @$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) $(MODE_FLAG) -c $< -o $@
63 |
64 | $(BUILD_DIR)/%.o: %.cpp
65 | @echo -e ' cxx\t $<'
66 | @$(CXX) $(CXXFLAGS) $(INCLUDES) $(DEFINES) $(MODE_FLAG) $(DEP_FLAGS) $<
67 | @$(CXX) $(CXXFLAGS) $(INCLUDES) $(DEFINES) $(MODE_FLAG) -c $< -o $@
68 |
69 | -include $(foreach f,$(notdir $(basename $(SRC))),$(DEP_DIR)/$(f).d)
70 |
71 | clean:
72 | @rm -f $(BIN_NAME)
73 | @rm -rf $(BUILD_DIR)
74 | @echo -e '\033[32m\033[1m clean done. \033[0m'
75 |
76 | help:
77 | @echo -e 'Makefile for Project WIPE-v2'
78 | @echo -e 'Author: Matt Yang'
79 | @echo -e 'make release -j4 \tbuild for actual use'
80 | @echo -e 'make debug -j4 \t\tbuild for development'
81 | @echo -e 'make clean \t\tnecessary when switching between "release" and "debug"'
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Project WIPE v2
2 |
3 | 
4 |
5 | ## 设计目标
6 |
7 | 本计划旨在通过制作自动化程序,来优化interactive,HMP,inputboost参数:
8 | This project aims to optimize the parameters of interactive, HMP, and inputboost by creating automated programs:
9 |
10 | - 现实负载采集(real world workload capture)
11 | - interactive调速器流程仿真(interactive governor process simulation)
12 | - 卡顿和耗电评分函数(cost function of lag and power comsuption)
13 | - 迭代取得局部最优(iteration to obtain local optimum)
14 |
15 | 相比[Project WIPE v1](https://github.com/yc9559/cpufreq-interactive-opt/):
16 |
17 | 1. 支持WALT HMP参数模拟
18 | 2. 支持input boost参数模拟
19 | 3. 全频率档位支持及可变参数序列长度
20 | 4. 毫秒级的负载序列和渲染的性能需求,来自systrace
21 | 5. 改进的续航和性能评分函数
22 | 6. 启发式优化算法使用NSGA-III
23 | 7. 同样的任务量和硬件条件下,优化执行效率提升~450%
24 |
25 | ## 如何使用
26 |
27 | 1. 编译发布版本`make release`
28 | 2. 修改配置文件`./conf.json`,选择要做优化的CPU模型列表,以及使用的负载序列和参数范围
29 | 3. 执行`mkdir output`创建输出文件夹
30 | 4. 执行`./wipe`,会自动加载`./conf.json`,并按照列表顺序依次执行优化
31 | 5. 到`output`输出文件夹,根据你的流畅度和耗电的要求,在候选中寻找合适的参数组合
32 | 6. 本项目在GCC 7.3测试通过
33 |
34 | ## 包含的第三方库
35 |
36 | - [nlohmann/json](https://github.com/nlohmann/json)
37 | - [OpenGA](https://github.com/Arash-codedev/openGA)
38 |
39 | ## Credit
40 |
41 | @TSU守望者
42 |
--------------------------------------------------------------------------------
/conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wipe v2 配置文件",
3 | "todoModels": [
4 | "./dataset/soc_model/model_sdm660.json",
5 | "./dataset/soc_model/model_sdm820.json",
6 | "./dataset/soc_model/model_sdm835.json",
7 | "./dataset/soc_model/model_sdm821_v1.json",
8 | "./dataset/soc_model/model_sdm821_v2.json",
9 | "./dataset/soc_model/model_sdm821_v3.json",
10 | "./dataset/soc_model/model_sdm625.json",
11 | "./dataset/soc_model/model_sdm626.json",
12 | "./dataset/soc_model/model_sdm636.json",
13 | "./dataset/soc_model/model_sdm650_652_653.json",
14 | "./dataset/soc_model/model_sdm616.json",
15 | "./dataset/soc_model/model_e8895.json",
16 | "./dataset/soc_model/model_e8890.json",
17 | "./dataset/soc_model/model_e7420.json"
18 | ],
19 | "mergedWorkload": "./dataset/workload/osborn/onscreen-merged.json",
20 | "idleWorkload": "./dataset/workload/osborn/offscreen-merged.json",
21 | "useUperf": true,
22 | "gaParameter": {
23 | "comment": "NSGA3优化算法参数,开启多线程后固定的随机数种子不能带来固定的结果,因为线程访问随机数的顺序不定",
24 | "population": 1536,
25 | "generationMax": 1000,
26 | "crossoverFraction": 0.95,
27 | "mutationRate": 0.05,
28 | "eta": 0.05,
29 | "threadNum": 12,
30 | "randomSeed": 23333
31 | },
32 | "miscSettings": {
33 | "comment": "亮屏基础功耗400mw 灭屏基础功耗30mw 卡顿评分常规占比1% 卡顿评分渲染掉帧占比99% 卡顿评分使用的分区卡顿计数分区长度为1000 连着卡顿2次认为是连续卡顿 连着卡顿4次认为是严重连续卡顿 连着卡顿至多2次 孤立卡顿权重0.02 连续卡顿权重1.00 严重连续卡顿权重1.00 性能需求大于足够快的性能容量的卡顿权重为0.25 interactive参数复杂度在性能占比4% 续航评分使用的分区耗电计数分区长度为2000 续航评分待机占比1% 续航评分亮屏占比99% 待机续航不低于参考的100% 卡顿比例不超过参考的120%",
34 | "sim.power.workingBase_mw": 400,
35 | "sim.power.idleBase_mw": 30,
36 | "eval.perf.commonFraction": 0.01,
37 | "eval.perf.renderFraction": 0.99,
38 | "eval.perf.partitionLen": 1000,
39 | "eval.perf.seqLagL1": 2,
40 | "eval.perf.seqLagL2": 4,
41 | "eval.perf.seqLagL0Scale": 0.02,
42 | "eval.perf.seqLagL1Scale": 1.00,
43 | "eval.perf.seqLagL2Scale": 1.00,
44 | "eval.perf.seqLagMax": 2,
45 | "eval.perf.enoughPenalty": 0.25,
46 | "eval.power.partitionLen": 2000,
47 | "eval.complexityFraction": 0.02,
48 | "ga.cost.batteryScore.idleFraction": 0.01,
49 | "ga.cost.batteryScore.workFraction": 0.99,
50 | "ga.cost.limit.idleLastingMin": 1.00,
51 | "ga.cost.limit.performanceMax": 1.20
52 | },
53 | "parameterRange": {
54 | "comment": "interactive, hmp, inputboost 参数优化范围,时长类参数单位为10ms(1个quantum)",
55 | "above_hispeed_delay": {
56 | "min": 1,
57 | "max": 10
58 | },
59 | "go_hispeed_load": {
60 | "min": 10,
61 | "max": 99
62 | },
63 | "max_freq_hysteresis": {
64 | "min": 0,
65 | "max": 0
66 | },
67 | "min_sample_time": {
68 | "min": 1,
69 | "max": 10
70 | },
71 | "target_loads": {
72 | "min": 1,
73 | "max": 99
74 | },
75 | "sched_downmigrate": {
76 | "min": 30,
77 | "max": 95
78 | },
79 | "sched_upmigrate": {
80 | "min": 30,
81 | "max": 95
82 | },
83 | "sched_ravg_hist_size": {
84 | "min": 5,
85 | "max": 5
86 | },
87 | "sched_window_stats_policy": {
88 | "min": 2,
89 | "max": 2
90 | },
91 | "sched_boost": {
92 | "min": 0,
93 | "max": 0
94 | },
95 | "timer_rate": {
96 | "min": 2,
97 | "max": 2
98 | },
99 | "input_duration": {
100 | "min": 0,
101 | "max": 300
102 | },
103 | "load_avg_period_ms": {
104 | "min": 128,
105 | "max": 128
106 | },
107 | "down_threshold": {
108 | "min": 214,
109 | "max": 214
110 | },
111 | "up_threshold": {
112 | "min": 524,
113 | "max": 524
114 | },
115 | "boost": {
116 | "min": 0,
117 | "max": 0
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/dataset/soc_model/README.md:
--------------------------------------------------------------------------------
1 | efficiency: 1024为A53作为基准值
2 | 功耗测试: GPU FLOPS
--------------------------------------------------------------------------------
/dataset/soc_model/model_e7420.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "e7420",
3 | "device": "三星 S6",
4 | "enoughCapacityPct": 80,
5 | "sched": "pelt",
6 | "intra": "smp",
7 | "inputBoost": false,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 400,
13 | "maxFreq": 1500,
14 | "opp": [
15 | 400,
16 | 500,
17 | 600,
18 | 700,
19 | 800,
20 | 900,
21 | 1000,
22 | 1100,
23 | 1200,
24 | 1300,
25 | 1400,
26 | 1500
27 | ],
28 | "corePower": [
29 | 28,
30 | 37,
31 | 53,
32 | 68,
33 | 84,
34 | 100,
35 | 124,
36 | 148,
37 | 184,
38 | 216,
39 | 256,
40 | 296
41 | ],
42 | "clusterPower": [
43 | 7,
44 | 9,
45 | 13,
46 | 17,
47 | 21,
48 | 25,
49 | 31,
50 | 37,
51 | 46,
52 | 54,
53 | 64,
54 | 74
55 | ],
56 | "author": "yc9559@酷安",
57 | "comment": "回归估计 https://www.anandtech.com/show/9330/exynos-7420-deep-dive/5"
58 | },
59 | {
60 | "coreNum": 4,
61 | "efficiency": 1536,
62 | "minFreq": 800,
63 | "maxFreq": 2100,
64 | "opp": [
65 | 800,
66 | 900,
67 | 1000,
68 | 1100,
69 | 1200,
70 | 1300,
71 | 1400,
72 | 1500,
73 | 1600,
74 | 1700,
75 | 1800,
76 | 1896,
77 | 2000,
78 | 2100
79 | ],
80 | "corePower": [
81 | 208,
82 | 240,
83 | 264,
84 | 304,
85 | 368,
86 | 416,
87 | 480,
88 | 528,
89 | 624,
90 | 720,
91 | 840,
92 | 992,
93 | 1184,
94 | 1440
95 | ],
96 | "clusterPower": [
97 | 52,
98 | 60,
99 | 66,
100 | 76,
101 | 92,
102 | 104,
103 | 120,
104 | 132,
105 | 156,
106 | 180,
107 | 210,
108 | 248,
109 | 296,
110 | 360
111 | ],
112 | "author": "yc9559@酷安",
113 | "comment": "回归估计 https://www.anandtech.com/show/9330/exynos-7420-deep-dive/5"
114 | }
115 | ]
116 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_e8890.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "e8890",
3 | "device": "三星 S7",
4 | "enoughCapacityPct": 71,
5 | "sched": "pelt",
6 | "intra": "smp",
7 | "inputBoost": false,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 442,
13 | "maxFreq": 1586,
14 | "opp": [
15 | 442,
16 | 546,
17 | 754,
18 | 858,
19 | 962,
20 | 1066,
21 | 1170,
22 | 1274,
23 | 1378,
24 | 1482,
25 | 1586
26 | ],
27 | "corePower": [
28 | 40,
29 | 46,
30 | 58,
31 | 64,
32 | 70,
33 | 78,
34 | 88,
35 | 96,
36 | 110,
37 | 124,
38 | 144
39 | ],
40 | "clusterPower": [
41 | 10,
42 | 12,
43 | 14,
44 | 16,
45 | 18,
46 | 19,
47 | 22,
48 | 24,
49 | 28,
50 | 31,
51 | 36
52 | ],
53 | "author": "yc9559@酷安",
54 | "comment": "使用骁龙660小核数据线性回归"
55 | },
56 | {
57 | "coreNum": 4,
58 | "efficiency": 1638,
59 | "minFreq": 728,
60 | "maxFreq": 2600,
61 | "opp": [
62 | 728,
63 | 832,
64 | 936,
65 | 1040,
66 | 1144,
67 | 1248,
68 | 1352,
69 | 1456,
70 | 1560,
71 | 1664,
72 | 1768,
73 | 1872,
74 | 1976,
75 | 2080,
76 | 2184,
77 | 2288,
78 | 2392,
79 | 2496,
80 | 2600
81 | ],
82 | "corePower": [
83 | 208,
84 | 256,
85 | 304,
86 | 352,
87 | 408,
88 | 464,
89 | 520,
90 | 576,
91 | 656,
92 | 736,
93 | 832,
94 | 944,
95 | 1072,
96 | 1216,
97 | 1392,
98 | 1592,
99 | 1832,
100 | 2184,
101 | 2672
102 | ],
103 | "clusterPower": [
104 | 52,
105 | 64,
106 | 76,
107 | 88,
108 | 102,
109 | 116,
110 | 130,
111 | 144,
112 | 164,
113 | 184,
114 | 208,
115 | 236,
116 | 268,
117 | 304,
118 | 348,
119 | 398,
120 | 458,
121 | 546,
122 | 668
123 | ],
124 | "author": "yc9559@酷安",
125 | "comment": "使用i冰宇宙数据估计 https://www.zhihu.com/question/37422042/answer/88962138"
126 | }
127 | ]
128 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_e8895.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "e8895",
3 | "device": "三星 S8",
4 | "enoughCapacityPct": 83,
5 | "sched": "pelt",
6 | "intra": "smp",
7 | "inputBoost": false,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 455,
13 | "maxFreq": 1690,
14 | "opp": [
15 | 455,
16 | 598,
17 | 715,
18 | 832,
19 | 949,
20 | 1053,
21 | 1248,
22 | 1456,
23 | 1690
24 | ],
25 | "corePower": [
26 | 78,
27 | 91,
28 | 104,
29 | 114,
30 | 125,
31 | 136,
32 | 158,
33 | 184,
34 | 224
35 | ],
36 | "clusterPower": [
37 | 19,
38 | 23,
39 | 26,
40 | 28,
41 | 31,
42 | 34,
43 | 40,
44 | 46,
45 | 56
46 | ],
47 | "author": "yc9559@酷安",
48 | "comment": "使用骁龙835小核数据线性回归"
49 | },
50 | {
51 | "coreNum": 4,
52 | "efficiency": 1664,
53 | "minFreq": 741,
54 | "maxFreq": 2314,
55 | "opp": [
56 | 741,
57 | 858,
58 | 962,
59 | 1066,
60 | 1170,
61 | 1261,
62 | 1469,
63 | 1703,
64 | 1807,
65 | 1937,
66 | 2002,
67 | 2158,
68 | 2314
69 | ],
70 | "corePower": [
71 | 196,
72 | 235,
73 | 274,
74 | 313,
75 | 352,
76 | 420,
77 | 548,
78 | 743,
79 | 860,
80 | 1017,
81 | 1056,
82 | 1310,
83 | 1604
84 | ],
85 | "clusterPower": [
86 | 49,
87 | 59,
88 | 68,
89 | 78,
90 | 88,
91 | 105,
92 | 137,
93 | 186,
94 | 215,
95 | 254,
96 | 264,
97 | 328,
98 | 401
99 | ],
100 | "author": "yc9559@酷安",
101 | "comment": "使用水瓶实测数据线性回归"
102 | }
103 | ]
104 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm616.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm616",
3 | "device": "华为荣耀5x",
4 | "enoughCapacityPct": 89,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": false,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 200,
13 | "maxFreq": 1209,
14 | "opp": [
15 | 200,
16 | 249,
17 | 400,
18 | 499,
19 | 800,
20 | 998,
21 | 1113,
22 | 1209
23 | ],
24 | "corePower": [
25 | 48,
26 | 54,
27 | 80,
28 | 96,
29 | 144,
30 | 176,
31 | 200,
32 | 224
33 | ],
34 | "clusterPower": [
35 | 12,
36 | 14,
37 | 20,
38 | 24,
39 | 36,
40 | 44,
41 | 50,
42 | 56
43 | ],
44 | "author": "梦鲲@酷安",
45 | "comment": "使用峰值功耗估计"
46 | },
47 | {
48 | "coreNum": 4,
49 | "efficiency": 1024,
50 | "minFreq": 200,
51 | "maxFreq": 1497,
52 | "opp": [
53 | 200,
54 | 345,
55 | 400,
56 | 533,
57 | 800,
58 | 960,
59 | 1113,
60 | 1344,
61 | 1459,
62 | 1497
63 | ],
64 | "corePower": [
65 | 48,
66 | 68,
67 | 80,
68 | 104,
69 | 144,
70 | 172,
71 | 200,
72 | 288,
73 | 360,
74 | 400
75 | ],
76 | "clusterPower": [
77 | 12,
78 | 17,
79 | 20,
80 | 26,
81 | 36,
82 | 43,
83 | 50,
84 | 72,
85 | 90,
86 | 100
87 | ],
88 | "author": "梦鲲@酷安",
89 | "comment": "使用峰值功耗估计"
90 | }
91 | ]
92 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm625.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm625",
3 | "device": "模拟",
4 | "enoughCapacityPct": 89,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": false,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 652,
13 | "maxFreq": 2016,
14 | "opp": [
15 | 652,
16 | 1036,
17 | 1401,
18 | 1689,
19 | 1804,
20 | 1958,
21 | 2016
22 | ],
23 | "corePower": [
24 | 44,
25 | 68,
26 | 108,
27 | 176,
28 | 208,
29 | 256,
30 | 280
31 | ],
32 | "clusterPower": [
33 | 11,
34 | 17,
35 | 27,
36 | 44,
37 | 52,
38 | 64,
39 | 70
40 | ],
41 | "author": "yc9559@酷安",
42 | "comment": "sdm660 线性回归"
43 | }
44 | ]
45 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm626.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm626",
3 | "device": "模拟",
4 | "enoughCapacityPct": 80,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": true,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 652,
13 | "maxFreq": 2208,
14 | "opp": [
15 | 652,
16 | 1036,
17 | 1401,
18 | 1689,
19 | 1804,
20 | 1958,
21 | 2016,
22 | 2150,
23 | 2208
24 | ],
25 | "corePower": [
26 | 44,
27 | 68,
28 | 108,
29 | 176,
30 | 208,
31 | 256,
32 | 280,
33 | 336,
34 | 384
35 | ],
36 | "clusterPower": [
37 | 11,
38 | 17,
39 | 27,
40 | 44,
41 | 52,
42 | 64,
43 | 70,
44 | 84,
45 | 96
46 | ],
47 | "author": "yc9559@酷安",
48 | "comment": "sdm660 线性回归"
49 | }
50 | ]
51 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm636.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm636",
3 | "device": "坚果 Pro 2 模拟",
4 | "enoughCapacityPct": 95,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": true,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 633,
13 | "maxFreq": 1612,
14 | "opp": [
15 | 633,
16 | 902,
17 | 1113,
18 | 1401,
19 | 1536,
20 | 1612
21 | ],
22 | "corePower": [
23 | 44,
24 | 56,
25 | 76,
26 | 108,
27 | 148,
28 | 160
29 | ],
30 | "clusterPower": [
31 | 11,
32 | 14,
33 | 19,
34 | 27,
35 | 37,
36 | 40
37 | ],
38 | "author": "yc9559@酷安",
39 | "comment": "sdm660 线性回归"
40 | },
41 | {
42 | "coreNum": 4,
43 | "efficiency": 1638,
44 | "minFreq": 1113,
45 | "maxFreq": 1804,
46 | "opp": [
47 | 1113,
48 | 1401,
49 | 1747,
50 | 1804
51 | ],
52 | "corePower": [
53 | 340,
54 | 464,
55 | 688,
56 | 760
57 | ],
58 | "clusterPower": [
59 | 85,
60 | 116,
61 | 172,
62 | 190
63 | ],
64 | "author": "yc9559@酷安",
65 | "comment": "sdm660 线性回归"
66 | }
67 | ]
68 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm650_652_653.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm650_652_653",
3 | "device": "模拟",
4 | "enoughCapacityPct": 89,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": false,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 400,
13 | "maxFreq": 1401,
14 | "opp": [
15 | 400,
16 | 691,
17 | 806,
18 | 1017,
19 | 1190,
20 | 1305,
21 | 1382,
22 | 1401
23 | ],
24 | "corePower": [
25 | 48,
26 | 64,
27 | 76,
28 | 108,
29 | 148,
30 | 176,
31 | 200,
32 | 208
33 | ],
34 | "clusterPower": [
35 | 12,
36 | 16,
37 | 19,
38 | 27,
39 | 37,
40 | 44,
41 | 50,
42 | 52
43 | ],
44 | "author": "yc9559@酷安",
45 | "comment": "P = C * freq * volt^2 趋势估计"
46 | },
47 | {
48 | "coreNum": 4,
49 | "efficiency": 1536,
50 | "minFreq": 400,
51 | "maxFreq": 1804,
52 | "opp": [
53 | 400,
54 | 883,
55 | 940,
56 | 998,
57 | 1056,
58 | 1113,
59 | 1190,
60 | 1248,
61 | 1305,
62 | 1382,
63 | 1612,
64 | 1747,
65 | 1804
66 | ],
67 | "corePower": [
68 | 176,
69 | 336,
70 | 360,
71 | 400,
72 | 448,
73 | 480,
74 | 544,
75 | 592,
76 | 640,
77 | 704,
78 | 1000,
79 | 1240,
80 | 1440
81 | ],
82 | "clusterPower": [
83 | 44,
84 | 84,
85 | 90,
86 | 100,
87 | 112,
88 | 120,
89 | 136,
90 | 148,
91 | 160,
92 | 176,
93 | 250,
94 | 310,
95 | 360
96 | ],
97 | "author": "yc9559@酷安",
98 | "comment": "P = C * freq * volt^2 趋势估计"
99 | }
100 | ]
101 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm660.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm660",
3 | "device": "坚果 Pro 2",
4 | "enoughCapacityPct": 88,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": true,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 633,
13 | "maxFreq": 1843,
14 | "opp": [
15 | 633,
16 | 902,
17 | 1113,
18 | 1401,
19 | 1536,
20 | 1747,
21 | 1843
22 | ],
23 | "corePower": [
24 | 44,
25 | 56,
26 | 76,
27 | 108,
28 | 148,
29 | 188,
30 | 212
31 | ],
32 | "clusterPower": [
33 | 11,
34 | 14,
35 | 19,
36 | 27,
37 | 37,
38 | 47,
39 | 53
40 | ],
41 | "author": "yc9559@酷安",
42 | "comment": "GPUFLOPS-1.60-MIX2-1T-32KB-2s-cpubind-2min"
43 | },
44 | {
45 | "coreNum": 4,
46 | "efficiency": 1638,
47 | "minFreq": 1113,
48 | "maxFreq": 2208,
49 | "opp": [
50 | 1113,
51 | 1401,
52 | 1747,
53 | 1958,
54 | 2150,
55 | 2208
56 | ],
57 | "corePower": [
58 | 340,
59 | 464,
60 | 688,
61 | 880,
62 | 1072,
63 | 1456
64 | ],
65 | "clusterPower": [
66 | 85,
67 | 116,
68 | 172,
69 | 220,
70 | 268,
71 | 364
72 | ],
73 | "author": "yc9559@酷安",
74 | "comment": "GPUFLOPS-1.60-MIX2-1T-32KB-2s-cpubind-2min"
75 | }
76 | ]
77 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm820.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm820",
3 | "device": "小米5 模拟",
4 | "enoughCapacityPct": 79,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": true,
8 | "cluster": [
9 | {
10 | "coreNum": 2,
11 | "efficiency": 1664,
12 | "minFreq": 307,
13 | "maxFreq": 1593,
14 | "opp": [
15 | 307,
16 | 422,
17 | 480,
18 | 556,
19 | 652,
20 | 729,
21 | 844,
22 | 960,
23 | 1036,
24 | 1113,
25 | 1190,
26 | 1228,
27 | 1324,
28 | 1401,
29 | 1478,
30 | 1593
31 | ],
32 | "corePower": [
33 | 89,
34 | 118,
35 | 135,
36 | 161,
37 | 194,
38 | 228,
39 | 287,
40 | 359,
41 | 414,
42 | 473,
43 | 536,
44 | 570,
45 | 655,
46 | 735,
47 | 824,
48 | 955
49 | ],
50 | "clusterPower": [
51 | 22,
52 | 30,
53 | 34,
54 | 40,
55 | 49,
56 | 57,
57 | 72,
58 | 90,
59 | 103,
60 | 118,
61 | 134,
62 | 143,
63 | 164,
64 | 184,
65 | 206,
66 | 239
67 | ],
68 | "author": "yc9559@酷安",
69 | "comment": "使用叶落情殇实测数据线性回归"
70 | },
71 | {
72 | "coreNum": 2,
73 | "efficiency": 1664,
74 | "minFreq": 307,
75 | "maxFreq": 2150,
76 | "opp": [
77 | 307,
78 | 403,
79 | 480,
80 | 556,
81 | 652,
82 | 729,
83 | 806,
84 | 883,
85 | 940,
86 | 1036,
87 | 1113,
88 | 1190,
89 | 1248,
90 | 1324,
91 | 1401,
92 | 1478,
93 | 1555,
94 | 1632,
95 | 1708,
96 | 1785,
97 | 1824,
98 | 1920,
99 | 1996,
100 | 2073,
101 | 2150
102 | ],
103 | "corePower": [
104 | 84,
105 | 106,
106 | 122,
107 | 139,
108 | 182,
109 | 215,
110 | 253,
111 | 296,
112 | 321,
113 | 376,
114 | 422,
115 | 473,
116 | 524,
117 | 587,
118 | 659,
119 | 735,
120 | 828,
121 | 908,
122 | 1014,
123 | 1119,
124 | 1170,
125 | 1352,
126 | 1521,
127 | 1656,
128 | 1913
129 | ],
130 | "clusterPower": [
131 | 21,
132 | 26,
133 | 31,
134 | 35,
135 | 45,
136 | 54,
137 | 63,
138 | 74,
139 | 80,
140 | 94,
141 | 106,
142 | 118,
143 | 131,
144 | 147,
145 | 165,
146 | 184,
147 | 207,
148 | 227,
149 | 253,
150 | 280,
151 | 293,
152 | 338,
153 | 380,
154 | 414,
155 | 478
156 | ],
157 | "author": "yc9559@酷安",
158 | "comment": "使用叶落情殇实测数据线性回归"
159 | }
160 | ]
161 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm821_v1.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm821_v1",
3 | "device": "小米5p 模拟 1.6G 2.0G",
4 | "enoughCapacityPct": 85,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": true,
8 | "cluster": [
9 | {
10 | "coreNum": 2,
11 | "efficiency": 1664,
12 | "minFreq": 307,
13 | "maxFreq": 1593,
14 | "opp": [
15 | 307,
16 | 403,
17 | 480,
18 | 556,
19 | 652,
20 | 729,
21 | 806,
22 | 844,
23 | 883,
24 | 960,
25 | 1036,
26 | 1113,
27 | 1228,
28 | 1248,
29 | 1324,
30 | 1401,
31 | 1555,
32 | 1593
33 | ],
34 | "corePower": [
35 | 89,
36 | 118,
37 | 135,
38 | 161,
39 | 194,
40 | 228,
41 | 287,
42 | 312,
43 | 328,
44 | 384,
45 | 432,
46 | 473,
47 | 570,
48 | 584,
49 | 655,
50 | 735,
51 | 880,
52 | 955
53 | ],
54 | "clusterPower": [
55 | 22,
56 | 30,
57 | 34,
58 | 40,
59 | 49,
60 | 57,
61 | 72,
62 | 78,
63 | 82,
64 | 96,
65 | 108,
66 | 118,
67 | 143,
68 | 146,
69 | 164,
70 | 184,
71 | 220,
72 | 239
73 | ],
74 | "author": "yc9559@酷安",
75 | "comment": "使用叶落情殇实测数据线性回归"
76 | },
77 | {
78 | "coreNum": 2,
79 | "efficiency": 1664,
80 | "minFreq": 307,
81 | "maxFreq": 1996,
82 | "opp": [
83 | 307,
84 | 403,
85 | 480,
86 | 556,
87 | 652,
88 | 729,
89 | 806,
90 | 844,
91 | 883,
92 | 960,
93 | 1036,
94 | 1113,
95 | 1228,
96 | 1248,
97 | 1324,
98 | 1401,
99 | 1555,
100 | 1593,
101 | 1632,
102 | 1708,
103 | 1824,
104 | 1920,
105 | 1996
106 | ],
107 | "corePower": [
108 | 84,
109 | 106,
110 | 122,
111 | 139,
112 | 182,
113 | 215,
114 | 253,
115 | 268,
116 | 296,
117 | 321,
118 | 376,
119 | 422,
120 | 488,
121 | 512,
122 | 587,
123 | 659,
124 | 828,
125 | 864,
126 | 908,
127 | 1014,
128 | 1170,
129 | 1352,
130 | 1521
131 | ],
132 | "clusterPower": [
133 | 21,
134 | 26,
135 | 31,
136 | 35,
137 | 45,
138 | 54,
139 | 63,
140 | 67,
141 | 74,
142 | 80,
143 | 94,
144 | 106,
145 | 122,
146 | 128,
147 | 147,
148 | 165,
149 | 207,
150 | 216,
151 | 227,
152 | 253,
153 | 293,
154 | 338,
155 | 380
156 | ],
157 | "author": "yc9559@酷安",
158 | "comment": "使用叶落情殇实测数据线性回归"
159 | }
160 | ]
161 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm821_v2.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm821_v2",
3 | "device": "小米5p 模拟 2.0G 2.1G",
4 | "enoughCapacityPct": 81,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": true,
8 | "cluster": [
9 | {
10 | "coreNum": 2,
11 | "efficiency": 1664,
12 | "minFreq": 307,
13 | "maxFreq": 1593,
14 | "opp": [
15 | 307,
16 | 384,
17 | 460,
18 | 537,
19 | 614,
20 | 691,
21 | 768,
22 | 844,
23 | 902,
24 | 979,
25 | 1056,
26 | 1132,
27 | 1209,
28 | 1286,
29 | 1363,
30 | 1440,
31 | 1516,
32 | 1593,
33 | 1996
34 | ],
35 | "corePower": [
36 | 74,
37 | 92,
38 | 113,
39 | 130,
40 | 148,
41 | 176,
42 | 204,
43 | 239,
44 | 271,
45 | 313,
46 | 348,
47 | 401,
48 | 454,
49 | 517,
50 | 563,
51 | 644,
52 | 715,
53 | 796,
54 | 1440
55 | ],
56 | "clusterPower": [
57 | 18,
58 | 23,
59 | 28,
60 | 33,
61 | 37,
62 | 44,
63 | 51,
64 | 60,
65 | 68,
66 | 78,
67 | 87,
68 | 100,
69 | 114,
70 | 129,
71 | 141,
72 | 161,
73 | 179,
74 | 199,
75 | 360
76 | ],
77 | "author": "yc9559@酷安",
78 | "comment": "使用叶落情殇实测数据线性回归"
79 | },
80 | {
81 | "coreNum": 2,
82 | "efficiency": 1664,
83 | "minFreq": 307,
84 | "maxFreq": 2150,
85 | "opp": [
86 | 307,
87 | 384,
88 | 460,
89 | 537,
90 | 614,
91 | 691,
92 | 748,
93 | 825,
94 | 902,
95 | 979,
96 | 1056,
97 | 1132,
98 | 1209,
99 | 1286,
100 | 1363,
101 | 1440,
102 | 1516,
103 | 1593,
104 | 1670,
105 | 1747,
106 | 1824,
107 | 1900,
108 | 1977,
109 | 2054,
110 | 2150
111 | ],
112 | "corePower": [
113 | 70,
114 | 84,
115 | 99,
116 | 113,
117 | 127,
118 | 141,
119 | 155,
120 | 197,
121 | 225,
122 | 271,
123 | 317,
124 | 356,
125 | 412,
126 | 458,
127 | 524,
128 | 577,
129 | 648,
130 | 739,
131 | 803,
132 | 876,
133 | 975,
134 | 1091,
135 | 1186,
136 | 1345,
137 | 1595
138 | ],
139 | "clusterPower": [
140 | 18,
141 | 21,
142 | 25,
143 | 28,
144 | 32,
145 | 35,
146 | 39,
147 | 49,
148 | 56,
149 | 68,
150 | 79,
151 | 89,
152 | 103,
153 | 114,
154 | 131,
155 | 144,
156 | 162,
157 | 185,
158 | 201,
159 | 219,
160 | 244,
161 | 273,
162 | 297,
163 | 336,
164 | 399
165 | ],
166 | "author": "yc9559@酷安",
167 | "comment": "使用叶落情殇实测数据线性回归"
168 | }
169 | ]
170 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm821_v3.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm821_v3",
3 | "device": "ZUK Edge 2.1G 2.3G",
4 | "enoughCapacityPct": 74,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": true,
8 | "cluster": [
9 | {
10 | "coreNum": 2,
11 | "efficiency": 1664,
12 | "minFreq": 307,
13 | "maxFreq": 1593,
14 | "opp": [
15 | 307,
16 | 384,
17 | 460,
18 | 537,
19 | 614,
20 | 691,
21 | 768,
22 | 844,
23 | 902,
24 | 979,
25 | 1056,
26 | 1132,
27 | 1209,
28 | 1286,
29 | 1363,
30 | 1440,
31 | 1516,
32 | 1593,
33 | 2188
34 | ],
35 | "corePower": [
36 | 74,
37 | 92,
38 | 113,
39 | 130,
40 | 148,
41 | 176,
42 | 204,
43 | 239,
44 | 271,
45 | 313,
46 | 348,
47 | 401,
48 | 454,
49 | 517,
50 | 563,
51 | 644,
52 | 715,
53 | 796,
54 | 1820
55 | ],
56 | "clusterPower": [
57 | 18,
58 | 23,
59 | 28,
60 | 33,
61 | 37,
62 | 44,
63 | 51,
64 | 60,
65 | 68,
66 | 78,
67 | 87,
68 | 100,
69 | 114,
70 | 129,
71 | 141,
72 | 161,
73 | 179,
74 | 199,
75 | 455
76 | ],
77 | "author": "yc9559@酷安",
78 | "comment": "使用叶落情殇实测数据"
79 | },
80 | {
81 | "coreNum": 2,
82 | "efficiency": 1664,
83 | "minFreq": 307,
84 | "maxFreq": 2342,
85 | "opp": [
86 | 307,
87 | 384,
88 | 460,
89 | 537,
90 | 614,
91 | 691,
92 | 748,
93 | 825,
94 | 902,
95 | 979,
96 | 1056,
97 | 1132,
98 | 1209,
99 | 1286,
100 | 1363,
101 | 1440,
102 | 1516,
103 | 1593,
104 | 1670,
105 | 1747,
106 | 1824,
107 | 1900,
108 | 1977,
109 | 2054,
110 | 2150,
111 | 2246,
112 | 2342
113 | ],
114 | "corePower": [
115 | 70,
116 | 84,
117 | 99,
118 | 113,
119 | 127,
120 | 141,
121 | 155,
122 | 197,
123 | 225,
124 | 271,
125 | 317,
126 | 356,
127 | 412,
128 | 458,
129 | 524,
130 | 577,
131 | 648,
132 | 739,
133 | 803,
134 | 876,
135 | 975,
136 | 1091,
137 | 1186,
138 | 1345,
139 | 1595,
140 | 1820,
141 | 2010
142 | ],
143 | "clusterPower": [
144 | 18,
145 | 21,
146 | 25,
147 | 28,
148 | 32,
149 | 35,
150 | 39,
151 | 49,
152 | 56,
153 | 68,
154 | 79,
155 | 89,
156 | 103,
157 | 114,
158 | 131,
159 | 144,
160 | 162,
161 | 185,
162 | 201,
163 | 219,
164 | 244,
165 | 273,
166 | 297,
167 | 336,
168 | 399,
169 | 455,
170 | 502
171 | ],
172 | "author": "yc9559@酷安",
173 | "comment": "使用叶落情殇实测数据"
174 | }
175 | ]
176 | }
--------------------------------------------------------------------------------
/dataset/soc_model/model_sdm835.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sdm835",
3 | "device": "小米6 模拟",
4 | "enoughCapacityPct": 83,
5 | "sched": "walt",
6 | "intra": "smp",
7 | "inputBoost": true,
8 | "cluster": [
9 | {
10 | "coreNum": 4,
11 | "efficiency": 1024,
12 | "minFreq": 300,
13 | "maxFreq": 1900,
14 | "opp": [
15 | 300,
16 | 364,
17 | 441,
18 | 518,
19 | 595,
20 | 672,
21 | 748,
22 | 825,
23 | 883,
24 | 960,
25 | 1036,
26 | 1094,
27 | 1171,
28 | 1248,
29 | 1324,
30 | 1401,
31 | 1478,
32 | 1555,
33 | 1670,
34 | 1747,
35 | 1824,
36 | 1900
37 | ],
38 | "corePower": [
39 | 67,
40 | 70,
41 | 77,
42 | 84,
43 | 92,
44 | 99,
45 | 106,
46 | 113,
47 | 120,
48 | 127,
49 | 134,
50 | 141,
51 | 151,
52 | 158,
53 | 165,
54 | 172,
55 | 183,
56 | 194,
57 | 208,
58 | 218,
59 | 229,
60 | 257
61 | ],
62 | "clusterPower": [
63 | 17,
64 | 18,
65 | 19,
66 | 21,
67 | 23,
68 | 25,
69 | 26,
70 | 28,
71 | 30,
72 | 32,
73 | 33,
74 | 35,
75 | 38,
76 | 40,
77 | 41,
78 | 43,
79 | 46,
80 | 48,
81 | 52,
82 | 55,
83 | 57,
84 | 64
85 | ],
86 | "author": "yc9559@酷安",
87 | "comment": "使用叶落情殇实测数据线性回归"
88 | },
89 | {
90 | "coreNum": 4,
91 | "efficiency": 1638,
92 | "minFreq": 300,
93 | "maxFreq": 2361,
94 | "opp": [
95 | 300,
96 | 345,
97 | 422,
98 | 499,
99 | 576,
100 | 652,
101 | 729,
102 | 806,
103 | 902,
104 | 979,
105 | 1056,
106 | 1132,
107 | 1190,
108 | 1267,
109 | 1344,
110 | 1420,
111 | 1497,
112 | 1574,
113 | 1651,
114 | 1728,
115 | 1804,
116 | 1881,
117 | 1958,
118 | 2035,
119 | 2112,
120 | 2265,
121 | 2342,
122 | 2361,
123 | 2457
124 | ],
125 | "corePower": [
126 | 137,
127 | 141,
128 | 155,
129 | 169,
130 | 176,
131 | 190,
132 | 204,
133 | 215,
134 | 232,
135 | 243,
136 | 253,
137 | 264,
138 | 285,
139 | 306,
140 | 334,
141 | 359,
142 | 394,
143 | 433,
144 | 468,
145 | 496,
146 | 549,
147 | 605,
148 | 655,
149 | 722,
150 | 792,
151 | 1021,
152 | 1126,
153 | 1144,
154 | 1338
155 | ],
156 | "clusterPower": [
157 | 34,
158 | 35,
159 | 39,
160 | 42,
161 | 44,
162 | 48,
163 | 51,
164 | 54,
165 | 58,
166 | 61,
167 | 63,
168 | 66,
169 | 71,
170 | 77,
171 | 84,
172 | 90,
173 | 99,
174 | 108,
175 | 117,
176 | 124,
177 | 137,
178 | 151,
179 | 164,
180 | 180,
181 | 198,
182 | 255,
183 | 282,
184 | 286,
185 | 334
186 | ],
187 | "author": "yc9559@酷安",
188 | "comment": "使用叶落情殇实测数据线性回归"
189 | }
190 | ]
191 | }
--------------------------------------------------------------------------------
/dataset/soc_model/raw/e7420.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/e7420.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/e8890.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/e8890.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/e8895.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/e8895.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/sd626.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/sd626.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/sd820.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/sd820.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/sd821.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/sd821.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/sd835.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/sd835.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/sdm616.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/sdm616.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/sdm636.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/sdm636.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/sdm650.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/dataset/soc_model/raw/sdm650.xlsx
--------------------------------------------------------------------------------
/dataset/soc_model/raw/sdm660.csv:
--------------------------------------------------------------------------------
1 | item,GPUFLOPS-1.60-MIX2-1T-32KB-2s-cpubind-2min,,,,,
2 | cluster,freq,totalpwr,pwr,perf/pwr,corepwr(0.8 * pwr),clusterpwr(0.2 * pwr)
3 | idle,,,795,,,
4 | little,633,850,55,11785.30909,44,11
5 | little,902,865,70,13194.97143,56,14
6 | little,1113,890,95,11996.96842,76,19
7 | little,1401,930,135,10626.84444,108,27
8 | little,1536,980,185,8501.967568,148,37
9 | little,1747,1030,235,7612.459574,188,47
10 | little,1843,1060,265,7121.630189,212,53
11 | big,1113,1220,425,4289.632941,340,85
12 | big,1401,1375,580,3956.617241,464,116
13 | big,1747,1675,860,3327.425581,688,172
14 | big,1958,1900,1100,2915.64,880,220
15 | big,2150,2130,1340,2628.134328,1072,268
16 | big,2208,2630,1820,1987.2,1456,364
17 |
--------------------------------------------------------------------------------
/dataset/workload/osborn/bili-download.json:
--------------------------------------------------------------------------------
1 | {"src":["bili-download.html"],"ver":1,"quantumSec":0.001,"windowQuantum":10,"frameQuantum":16,"efficiencyA53":1024,"efficiency":1638,"freq":2208,"loadScale":100,"coreNum":4,"windowedLoadLen":1332,"windowedLoad":[[25,13,25,1,0,0],[16,16,16,11,3,0],[23,15,23,3,2,0],[16,16,10,5,2,0],[13,12,13,9,3,0],[29,14,29,4,4,0],[26,22,26,7,2,0],[32,29,32,12,0,0],[17,9,17,0,0,0],[16,12,16,2,4,0],[23,23,16,6,1,0],[23,21,23,21,0,0],[29,13,29,2,0,0],[23,23,20,8,4,0],[13,9,13,1,1,0],[16,16,10,16,1,0],[21,21,15,6,0,0],[23,23,14,11,12,0],[25,25,21,10,4,0],[26,26,23,7,0,0],[2,2,1,0,0,0],[17,16,17,10,2,0],[28,28,19,16,5,0],[20,20,20,13,13,0],[51,51,26,16,12,0],[88,15,88,12,6,0],[70,37,70,17,10,0],[55,55,46,47,46,0],[43,21,43,9,18,0],[100,47,59,36,100,0],[20,20,13,3,15,0],[17,17,14,9,2,0],[25,14,25,5,0,0],[33,26,33,9,2,0],[26,21,26,16,2,0],[30,26,30,19,12,0],[17,17,13,10,6,0],[36,36,30,21,0,0],[47,47,31,39,17,0],[51,32,41,51,18,0],[36,36,28,29,7,0],[23,16,23,7,1,0],[23,23,14,6,7,0],[23,12,23,6,1,0],[25,18,25,11,3,0],[27,17,27,0,3,0],[26,21,26,8,1,0],[19,19,13,0,0,0],[21,19,21,8,0,0],[16,16,14,5,1,0],[34,21,34,6,9,0],[32,26,32,12,5,0],[33,15,33,6,2,0],[11,9,11,0,4,0],[21,21,19,6,7,0],[21,11,21,4,0,0],[27,13,27,0,0,0],[22,19,22,12,2,0],[26,20,26,9,9,0],[9,9,3,0,0,0],[24,22,24,10,0,0],[25,15,25,8,0,0],[22,14,22,7,4,0],[29,29,19,8,6,0],[20,12,20,1,4,0],[13,11,13,2,5,0],[21,21,8,4,8,0],[25,12,25,8,4,0],[24,14,24,9,6,0],[19,19,19,14,3,0],[7,7,6,0,0,0],[21,21,13,5,15,0],[22,19,22,6,3,0],[27,21,27,10,2,0],[26,26,15,7,17,0],[19,19,17,1,14,0],[9,9,9,0,0,0],[19,6,19,2,3,0],[25,24,25,4,4,0],[24,24,12,16,0,0],[22,17,22,10,10,0],[19,8,19,1,0,0],[24,24,11,6,10,0],[22,22,21,5,3,0],[25,19,25,4,3,0],[26,18,26,0,3,0],[24,24,20,6,3,0],[27,20,27,11,0,0],[15,15,8,4,7,0],[13,7,13,0,0,0],[26,15,26,1,1,0],[27,22,27,6,3,0],[56,56,27,33,13,0],[68,68,14,2,0,0],[71,71,22,20,4,0],[59,59,41,36,22,0],[27,14,27,5,0,0],[27,19,27,9,3,0],[27,24,27,4,2,0],[13,10,13,2,5,0],[15,15,6,6,8,0],[28,14,28,0,0,0],[29,15,29,5,5,0],[28,19,28,5,4,0],[24,24,14,12,17,0],[11,11,9,7,5,0],[16,16,13,7,9,0],[39,39,23,19,1,0],[26,22,26,7,4,0],[32,19,32,10,0,0],[20,14,20,10,5,0],[8,5,8,3,4,0],[23,18,23,12,1,0],[22,22,19,11,1,0],[29,19,29,9,7,0],[26,26,20,5,0,0],[12,10,12,1,0,0],[13,10,13,6,0,0],[29,29,26,8,3,0],[27,24,27,16,7,0],[19,15,19,0,0,0],[14,9,14,8,0,0],[20,20,18,8,3,0],[16,16,6,12,5,0],[74,74,38,23,27,0],[85,58,21,85,29,0],[74,38,34,74,6,0],[43,43,33,33,17,0],[23,23,13,10,16,0],[38,38,33,22,27,0],[50,50,30,11,1,0],[26,26,22,7,7,0],[24,24,19,8,2,0],[11,7,11,2,2,0],[17,17,17,2,4,0],[21,20,21,5,2,0],[31,27,31,14,18,0],[25,25,14,13,3,0],[68,51,68,20,9,0],[47,33,27,20,47,0],[30,30,30,22,1,0],[26,26,26,24,7,0],[31,25,31,15,4,0],[34,34,21,8,4,0],[14,14,10,3,0,0],[20,20,11,0,12,0],[30,21,30,8,6,0],[27,16,27,15,19,0],[25,24,25,4,3,0],[28,28,18,10,17,0],[9,9,6,3,1,0],[46,46,43,8,6,0],[24,22,24,11,1,0],[29,16,29,8,20,0],[24,24,24,14,11,0],[17,17,14,1,0,0],[14,14,12,8,3,0],[17,13,17,11,1,0],[24,20,24,2,1,0],[23,11,13,9,23,0],[12,9,12,2,4,0],[20,13,20,1,0,0],[22,22,18,5,4,0],[25,25,18,17,3,0],[27,19,27,14,1,0],[22,22,21,8,3,0],[12,12,12,3,0,0],[24,24,9,6,3,0],[26,19,26,1,0,0],[28,22,28,7,2,0],[30,17,30,8,0,0],[28,28,19,13,7,0],[8,7,8,2,0,0],[18,10,18,0,0,0],[24,16,24,10,0,0],[30,30,22,13,4,0],[27,18,27,4,1,0],[19,11,19,5,1,0],[24,24,17,8,8,0],[28,28,23,8,0,0],[25,20,25,7,2,0],[21,21,20,8,1,0],[30,12,30,2,1,0],[11,10,11,0,1,0],[23,17,23,7,3,0],[16,16,11,13,2,0],[25,25,15,6,8,0],[24,24,19,14,5,0],[24,20,24,8,4,0],[10,5,10,1,2,0],[14,14,13,7,2,0],[23,23,19,15,7,0],[23,23,22,6,6,0],[27,11,27,6,0,0],[21,10,21,0,0,0],[59,59,9,6,11,0],[27,15,27,4,1,0],[28,14,28,6,3,0],[29,14,29,0,0,0],[31,31,17,17,7,0],[0,0,0,0,0,0],[21,21,14,11,20,0],[24,15,24,6,1,0],[20,15,20,1,1,0],[28,26,28,6,2,0],[76,76,28,12,6,0],[46,46,22,17,11,0],[86,86,17,21,6,0],[52,49,52,22,6,0],[16,9,16,0,0,0],[15,7,15,3,2,0],[26,19,26,21,1,0],[25,20,25,8,0,0],[25,20,25,3,3,0],[15,12,15,8,2,0],[21,21,13,8,0,0],[20,9,20,0,0,0],[30,18,30,8,7,0],[23,18,23,15,0,0],[32,32,24,13,4,0],[14,10,14,0,0,0],[21,14,21,5,0,0],[21,7,21,1,4,0],[30,21,30,16,5,0],[42,42,18,29,10,0],[87,87,19,25,10,0],[75,75,19,2,1,0],[40,40,22,13,5,0],[50,50,36,30,32,0],[45,45,23,39,11,0],[29,17,29,5,2,0],[18,12,18,6,1,0],[17,14,17,12,0,0],[18,18,10,15,1,0],[41,22,41,9,0,0],[43,19,43,9,6,0],[18,14,18,3,0,0],[20,20,4,13,1,0],[59,59,42,30,9,0],[73,73,52,31,28,0],[29,16,29,3,9,0],[41,39,41,7,7,0],[26,26,16,15,0,0],[16,12,16,12,14,0],[31,12,31,2,2,0],[25,13,25,0,0,0],[25,18,25,11,0,0],[24,24,21,14,0,0],[14,8,14,3,0,0],[15,15,13,5,0,0],[26,12,26,2,1,0],[64,31,64,24,28,0],[100,29,100,24,14,0],[31,12,31,0,0,0],[14,13,14,5,1,0],[19,19,12,6,4,0],[23,23,22,6,16,0],[20,17,20,14,3,0],[28,20,28,10,2,0],[15,14,15,5,1,0],[13,13,9,2,7,0],[23,16,23,9,0,0],[27,20,27,4,2,0],[33,26,33,13,3,0],[15,12,15,4,3,0],[9,9,2,4,2,0],[30,15,30,7,0,0],[25,18,25,8,7,0],[29,21,29,11,0,0],[27,13,27,1,0,0],[15,15,14,4,1,0],[9,8,9,9,1,0],[25,14,25,0,0,0],[30,13,30,5,0,0],[26,26,24,3,3,0],[31,31,22,8,9,0],[16,11,16,4,0,0],[13,11,13,3,0,0],[16,14,16,10,0,0],[34,18,34,7,5,0],[22,14,22,15,3,0],[20,14,20,3,1,0],[18,11,18,4,0,0],[24,11,24,3,1,0],[21,21,17,4,5,0],[26,26,15,4,0,0],[28,15,28,2,2,0],[30,30,13,2,1,0],[15,15,9,4,4,0],[22,22,16,10,3,0],[27,15,27,5,3,0],[22,22,20,17,3,0],[13,7,13,1,0,0],[23,22,23,9,2,0],[16,10,16,11,2,0],[35,28,28,35,5,0],[25,14,25,2,5,0],[19,14,19,5,0,0],[16,16,13,12,1,0],[20,20,16,8,0,0],[24,22,24,9,9,0],[26,13,26,11,4,0],[24,15,24,11,1,0],[27,27,23,0,0,0],[44,44,30,7,0,0],[16,15,16,6,3,0],[24,16,24,8,2,0],[33,33,21,13,8,0],[31,31,16,2,7,0],[22,22,14,6,0,0],[9,9,5,2,0,0],[31,31,10,20,4,0],[25,16,25,7,0,0],[22,17,22,11,3,0],[27,26,27,7,3,0],[23,17,23,10,1,0],[11,5,11,3,0,0],[25,25,20,1,0,0],[93,93,34,31,15,0],[57,57,21,21,16,0],[84,84,40,28,6,0],[1,1,0,0,0,0],[21,16,21,2,4,0],[24,20,24,15,5,0],[57,57,55,25,27,0],[83,83,55,32,12,0],[83,83,10,18,12,0],[31,31,13,13,5,0],[55,55,41,36,21,0],[41,37,41,26,23,0],[29,19,29,9,2,0],[30,30,25,25,16,0],[10,10,8,4,0,0],[21,8,21,1,2,0],[22,18,22,8,2,0],[22,22,22,10,0,0],[1,1,0,0,0,0],[0,0,0,0,0,0],[59,47,59,13,21,0],[88,88,50,45,41,0],[38,38,29,24,21,0],[57,57,30,24,16,0],[27,16,27,4,0,0],[14,10,14,0,1,0],[20,16,20,6,1,0],[26,16,26,2,0,0],[23,23,21,5,0,0],[50,50,33,8,7,0],[17,17,12,3,1,0],[15,8,15,5,3,0],[23,22,23,9,22,0],[28,28,20,7,12,0],[25,21,25,15,1,0],[24,24,21,6,6,0],[13,7,13,1,0,0],[37,17,37,9,7,0],[26,18,26,7,5,0],[27,16,27,4,3,0],[28,13,28,9,9,0],[24,24,19,1,7,0],[11,9,11,4,2,0],[23,15,23,11,3,0],[25,20,25,6,3,0],[20,20,19,18,0,0],[26,25,26,8,3,0],[14,10,14,0,0,0],[24,16,24,3,0,0],[22,22,15,4,6,0],[24,17,24,16,5,0],[18,17,18,8,11,0],[22,22,18,12,1,0],[10,10,4,0,0,0],[17,17,16,11,2,0],[27,27,21,11,7,0],[24,12,24,5,4,0],[26,26,24,13,1,0],[20,20,15,11,2,0],[18,15,18,8,0,0],[17,14,17,3,2,0],[26,26,15,11,6,0],[24,24,18,14,3,0],[25,21,25,13,5,0],[11,11,5,6,1,0],[25,25,17,12,3,0],[32,32,19,10,3,0],[23,23,18,6,11,0],[34,18,34,0,0,0],[25,23,25,11,2,0],[12,8,12,3,1,0],[19,19,9,4,0,0],[29,14,29,0,0,0],[24,20,24,1,8,0],[29,29,23,10,2,0],[15,15,13,9,3,0],[24,10,24,1,4,0],[43,43,28,12,3,0],[23,22,23,16,7,0],[24,17,24,14,3,0],[24,24,23,7,0,0],[13,11,13,4,0,0],[29,29,15,5,4,0],[20,20,11,12,6,0],[21,18,21,17,0,0],[22,22,19,4,0,0],[21,17,21,15,13,0],[17,10,17,0,0,0],[16,4,16,2,0,0],[29,23,29,11,12,0],[25,25,22,16,5,0],[24,19,24,0,0,0],[24,16,24,8,0,0],[14,14,13,4,0,0],[20,20,11,3,11,0],[23,23,15,15,1,0],[26,18,26,6,2,0],[30,30,12,18,4,0],[23,17,23,2,4,0],[15,15,10,0,0,0],[17,3,17,1,0,0],[29,23,29,4,8,0],[22,16,22,10,4,0],[26,26,20,7,0,0],[25,19,25,5,2,0],[16,10,16,0,0,0],[31,31,23,3,1,0],[88,20,23,18,88,0],[64,54,40,13,64,0],[29,29,19,10,12,0],[53,53,30,25,35,0],[28,27,28,20,14,0],[97,97,31,23,28,0],[54,54,19,14,15,0],[61,61,25,18,4,0],[48,45,48,15,6,0],[25,25,25,8,2,0],[16,11,16,2,5,0],[24,21,24,10,8,0],[26,26,13,3,12,0],[24,24,24,7,3,0],[77,77,71,31,27,0],[45,45,42,18,22,0],[45,45,24,9,7,0],[29,29,29,11,3,0],[40,40,18,27,24,0],[24,23,24,17,3,0],[27,27,19,20,9,0],[27,20,27,12,4,0],[15,13,15,3,0,0],[15,15,14,9,1,0],[21,21,16,15,6,0],[24,17,24,8,0,0],[24,21,19,23,24,0],[40,40,29,18,13,0],[19,19,17,5,1,0],[10,10,4,8,4,0],[22,22,18,16,6,0],[25,14,25,9,2,0],[19,18,19,16,0,0],[28,16,28,6,0,0],[21,12,21,3,0,0],[14,14,9,5,3,0],[21,18,21,19,1,0],[20,14,20,3,0,0],[26,26,18,20,3,0],[28,19,28,7,3,0],[11,11,9,8,1,0],[19,19,9,3,3,0],[38,19,38,9,1,0],[28,17,28,2,1,0],[21,21,18,11,1,0],[28,20,28,7,0,0],[15,10,15,5,0,0],[14,14,14,9,1,0],[24,24,19,2,7,0],[28,28,15,7,4,0],[22,22,19,17,4,0],[18,17,18,4,2,0],[20,20,13,3,4,0],[15,12,15,2,0,0],[26,20,26,10,15,0],[30,30,20,4,0,0],[27,15,27,1,0,0],[14,13,14,10,0,0],[20,7,20,7,0,0],[15,12,15,10,0,0],[25,16,25,10,4,0],[63,63,14,15,1,0],[84,84,1,3,0,0],[5,4,5,1,0,0],[1,0,1,1,0,0],[2,2,0,0,0,0],[9,9,3,0,0,0],[6,6,1,1,1,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[4,4,1,0,0,0],[28,28,0,1,1,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[3,3,2,0,0,0],[2,2,0,1,0,0],[3,3,0,0,0,0],[7,4,7,0,0,0],[26,26,10,0,0,0],[2,2,0,1,0,0],[3,0,3,0,0,0],[0,0,0,0,0,0],[3,0,3,0,0,0],[17,3,17,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[2,0,2,0,0,0],[1,1,1,0,0,0],[47,47,43,15,6,0],[83,83,18,13,6,0],[6,6,3,0,0,0],[2,1,2,1,1,0],[1,1,0,0,0,0],[0,0,0,0,0,0],[7,7,3,2,3,0],[1,1,0,0,0,0],[2,2,0,1,1,0],[96,96,35,9,2,0],[58,43,58,29,24,0],[39,39,34,8,1,0],[100,100,22,50,27,0],[88,88,13,2,0,0],[11,11,11,8,2,0],[7,4,1,6,7,0],[11,11,9,1,1,0],[36,36,18,4,1,0],[15,15,12,2,1,0],[28,28,21,7,2,0],[71,71,57,34,19,0],[30,27,30,5,1,0],[51,51,46,40,30,0],[49,49,21,22,15,0],[45,40,45,19,10,0],[41,41,32,24,27,0],[32,32,32,13,7,0],[53,53,23,29,9,0],[33,30,33,11,0,0],[70,70,29,35,3,0],[81,81,31,27,17,0],[31,20,31,11,3,0],[30,30,27,11,4,0],[37,37,35,15,1,0],[41,41,30,19,10,0],[65,65,41,28,8,0],[55,55,38,23,11,0],[30,25,30,10,1,0],[52,52,47,18,16,0],[42,42,37,15,8,0],[72,72,42,38,19,0],[68,68,32,54,25,0],[36,29,13,36,1,0],[62,62,53,18,11,0],[35,35,19,24,4,0],[18,18,11,3,2,0],[57,53,57,7,10,0],[62,44,62,12,6,0],[52,52,37,22,7,0],[48,43,48,21,0,0],[52,18,19,17,52,0],[100,32,41,22,100,0],[39,39,28,20,21,0],[29,29,19,6,0,0],[49,49,40,20,9,0],[37,27,37,11,0,0],[44,38,44,17,3,0],[47,47,32,25,2,0],[34,34,28,9,0,0],[46,46,29,17,9,0],[49,49,36,19,9,0],[29,24,29,6,8,0],[54,33,54,20,7,0],[32,32,24,17,4,0],[41,41,39,20,6,0],[33,33,29,13,6,0],[20,18,20,14,4,0],[26,21,26,5,7,0],[16,15,16,4,0,0],[15,15,14,5,3,0],[20,20,14,9,0,0],[24,24,15,1,14,0],[24,24,21,15,10,0],[24,18,24,2,3,0],[15,15,12,0,0,0],[18,18,15,7,0,0],[24,24,22,9,4,0],[25,24,25,10,0,0],[21,21,20,15,2,0],[12,6,12,5,0,0],[17,17,15,12,1,0],[18,16,18,13,1,0],[20,18,20,13,3,0],[41,41,27,7,28,0],[23,23,22,11,4,0],[12,12,8,8,0,0],[17,17,5,5,5,0],[21,10,21,16,1,0],[22,21,22,17,8,0],[29,13,29,0,0,0],[17,15,17,4,2,0],[17,17,17,6,0,0],[16,7,16,10,2,0],[16,15,16,14,3,0],[24,21,24,10,7,0],[24,24,19,8,1,0],[11,11,3,3,3,0],[0,0,0,0,0,0],[10,10,3,0,0,0],[1,1,0,0,0,0],[5,5,0,0,1,0],[0,0,0,0,0,0],[3,1,3,0,0,0],[1,1,1,0,0,0],[3,3,0,2,1,0],[1,0,1,0,0,0],[7,2,7,0,1,0],[6,2,6,0,0,0],[32,32,30,22,2,0],[42,42,18,13,2,0],[35,18,35,2,1,0],[47,47,15,5,1,0],[87,29,29,87,14,0],[59,25,32,59,19,0],[43,43,26,10,9,0],[15,8,15,7,0,0],[30,28,30,7,8,0],[24,23,24,4,3,0],[57,37,57,29,28,0],[52,40,52,21,11,0],[29,29,17,11,5,0],[17,12,17,3,2,0],[22,22,15,3,1,0],[19,17,19,6,4,0],[26,26,21,11,3,0],[23,23,21,10,3,0],[32,32,17,5,8,0],[27,27,24,7,5,0],[57,57,25,17,14,0],[27,27,26,10,5,0],[68,68,40,26,8,0],[65,65,11,14,6,0],[58,58,28,13,5,0],[17,17,14,8,3,0],[25,25,18,6,6,0],[21,14,21,14,0,0],[24,24,24,18,2,0],[26,25,26,5,1,0],[40,22,40,13,5,0],[12,12,11,6,2,0],[14,14,14,7,2,0],[34,28,34,9,7,0],[27,18,27,13,3,0],[25,25,23,8,8,0],[23,23,22,6,10,0],[16,13,16,7,3,0],[95,95,37,26,9,0],[17,17,17,8,5,0],[28,28,18,11,3,0],[22,21,22,10,3,0],[23,23,21,12,3,0],[14,10,14,4,0,0],[20,20,12,7,3,0],[21,21,19,6,3,0],[28,28,13,10,8,0],[20,20,20,14,2,0],[25,16,25,11,5,0],[14,14,12,6,0,0],[24,24,13,8,3,0],[21,21,18,5,9,0],[29,29,22,9,4,0],[24,24,24,10,5,0],[30,21,30,6,1,0],[13,8,13,3,0,0],[26,26,12,5,3,0],[18,18,12,7,9,0],[23,22,23,9,4,0],[24,20,24,13,1,0],[24,24,19,14,5,0],[14,14,10,7,0,0],[23,23,14,5,2,0],[20,20,19,7,7,0],[24,24,20,11,0,0],[21,21,17,13,6,0],[24,24,24,5,8,0],[9,9,8,4,0,0],[19,19,10,10,0,0],[21,21,18,12,7,0],[29,19,29,5,3,0],[23,23,20,14,1,0],[24,19,24,18,2,0],[13,13,10,2,2,0],[28,28,14,7,3,0],[48,48,35,13,5,0],[79,79,23,21,3,0],[56,56,41,23,6,0],[23,18,23,6,0,0],[13,12,13,3,1,0],[15,15,14,4,0,0],[28,14,28,1,1,0],[24,19,24,5,8,0],[28,15,28,4,0,0],[13,8,13,3,0,0],[10,7,10,8,1,0],[27,26,27,8,8,0],[28,28,27,4,0,0],[24,21,24,15,0,0],[37,14,37,5,4,0],[16,8,16,1,0,0],[16,16,16,6,5,0],[17,12,17,9,0,0],[23,14,23,8,6,0],[23,23,20,15,7,0],[25,22,25,3,0,0],[13,4,13,0,0,0],[10,9,8,6,10,0],[23,14,23,9,11,0],[24,16,24,6,4,0],[20,20,15,15,1,0],[24,24,22,9,4,0],[12,11,12,7,4,0],[59,59,39,4,7,0],[73,73,57,40,32,0],[84,84,40,26,22,0],[42,42,26,34,15,0],[21,21,19,3,0,0],[20,20,13,5,5,0],[27,16,27,2,1,0],[41,41,26,41,21,0],[39,39,22,17,37,0],[22,22,22,7,1,0],[27,20,27,10,2,0],[16,16,16,1,0,0],[20,20,13,6,0,0],[23,10,23,3,0,0],[31,31,20,6,3,0],[27,27,19,3,7,0],[19,17,19,6,4,0],[54,54,40,32,26,0],[100,88,46,100,62,0],[100,24,38,100,5,0],[82,82,50,52,43,0],[99,99,55,34,29,0],[72,39,72,23,11,0],[32,32,11,17,8,0],[45,13,45,4,4,0],[23,21,23,7,5,0],[27,27,15,12,5,0],[31,12,31,9,9,0],[46,46,31,38,22,0],[16,15,16,8,6,0],[21,15,21,7,1,0],[26,26,20,9,14,0],[44,44,17,22,21,0],[23,23,21,17,1,0],[25,25,18,9,8,0],[11,11,7,4,1,0],[12,12,9,11,4,0],[20,20,14,3,9,0],[25,16,25,6,2,0],[23,23,19,12,8,0],[13,13,8,9,0,0],[12,12,9,11,1,0],[24,15,24,3,5,0],[22,22,20,3,14,0],[26,26,16,5,11,0],[5,3,5,1,0,0],[22,15,22,1,0,0],[22,18,22,10,3,0],[21,21,18,6,3,0],[23,23,14,7,0,0],[17,17,14,8,1,0],[19,18,19,1,8,0],[18,11,18,0,0,0],[22,17,22,3,0,0],[25,25,24,10,1,0],[24,20,24,7,11,0],[15,15,14,10,4,0],[13,11,13,3,1,0],[15,15,15,12,1,0],[23,18,23,17,4,0],[26,19,26,7,2,0],[27,19,27,9,1,0],[15,15,9,3,0,0],[44,44,16,9,14,0],[23,15,23,6,1,0],[0,0,0,0,0,0],[32,17,32,10,0,0],[24,24,24,17,18,0],[20,16,20,8,0,0],[10,7,10,6,1,0],[20,20,12,14,3,0],[22,14,22,2,4,0],[40,40,18,14,20,0],[19,16,10,15,19,0],[7,6,4,7,1,0],[21,16,21,20,5,0],[26,17,26,9,0,0],[18,18,18,5,13,0],[19,11,19,4,4,0],[15,15,10,8,0,0],[21,15,21,3,0,0],[21,21,20,6,7,0],[28,24,28,7,2,0],[35,33,35,25,11,0],[87,87,19,11,16,0],[45,45,13,12,1,0],[73,73,41,24,14,0],[23,23,18,8,13,0],[22,19,22,11,1,0],[23,23,19,12,1,0],[10,10,6,2,0,0],[27,27,20,7,1,0],[28,15,28,0,0,0],[24,13,24,11,1,0],[9,9,7,4,5,0],[25,18,25,3,4,0],[17,15,17,9,15,0],[21,15,21,6,3,0],[32,32,14,14,7,0],[24,24,22,8,0,0],[40,40,18,17,11,0],[30,19,30,6,9,0],[100,14,100,23,12,0],[48,40,48,27,18,0],[19,18,19,5,2,0],[30,30,29,28,8,0],[21,21,6,3,1,0],[45,45,31,20,11,0],[46,46,34,9,9,0],[27,19,27,9,3,0],[31,21,31,5,3,0],[30,19,30,7,0,0],[16,9,16,5,2,0],[16,16,7,5,0,0],[25,23,25,2,1,0],[31,31,13,17,10,0],[25,16,25,10,1,0],[39,31,39,22,29,0],[70,70,46,47,30,0],[24,24,22,23,11,0],[49,49,8,33,8,0],[19,19,18,8,7,0],[32,32,24,17,7,0],[19,19,18,11,1,0],[11,11,3,4,3,0],[27,26,27,7,2,0],[27,19,27,7,3,0],[22,19,22,1,0,0],[40,40,15,13,1,0],[6,0,6,2,2,0],[2,2,1,2,1,0],[4,4,3,0,1,0],[0,0,0,0,0,0],[30,17,30,6,2,0],[27,18,27,5,1,0],[14,14,9,13,2,0],[11,11,10,8,0,0],[20,20,16,4,8,0],[25,25,19,11,6,0],[61,35,61,22,9,0],[100,26,100,24,14,0],[34,12,34,3,0,0],[13,9,13,5,4,0],[17,17,12,7,4,0],[25,18,25,10,1,0],[27,27,18,9,3,0],[25,22,25,4,4,0],[14,11,14,11,0,0],[11,11,6,11,0,0],[26,26,18,16,4,0],[22,18,22,8,3,0],[32,32,13,20,5,0],[11,9,11,0,0,0],[21,11,21,5,2,0],[14,14,11,10,0,0],[33,22,33,7,3,0],[22,17,22,11,5,0],[22,19,22,11,1,0],[10,10,7,5,0,0],[14,9,14,9,1,0],[15,12,15,6,13,0],[26,16,26,5,0,0],[24,21,24,6,3,0],[33,33,29,4,2,0],[13,11,13,2,5,0],[17,7,17,4,0,0],[26,11,26,0,0,0],[27,27,15,24,11,0],[28,22,28,5,1,0],[9,8,9,3,0,0],[14,10,14,1,0,0],[29,25,29,4,5,0],[15,15,15,0,13,0],[44,17,44,13,4,0],[16,16,16,15,1,0],[21,21,11,9,5,0],[13,13,8,7,2,0],[25,25,15,11,0,0],[19,17,19,3,9,0],[29,29,19,11,7,0],[20,19,20,2,4,0],[7,7,4,0,0,0],[25,11,25,3,1,0],[14,14,13,9,12,0],[35,35,20,16,2,0],[25,14,25,0,0,0],[20,20,16,16,4,0],[19,19,15,1,1,0],[16,14,16,8,1,0],[18,18,15,17,0,0],[20,20,19,10,4,0],[26,24,26,8,4,0],[14,10,14,7,2,0],[17,14,17,0,0,0],[26,9,26,0,0,0],[33,33,19,10,5,0],[60,60,40,19,9,0],[71,71,25,20,7,0],[70,70,18,29,4,0],[60,60,23,11,3,0],[44,44,41,1,0,0],[65,30,65,32,19,0],[91,26,91,17,21,0],[79,41,79,40,32,0],[23,23,16,9,6,0],[34,34,8,10,14,0],[23,17,12,23,4,0],[44,44,37,20,23,0],[23,23,8,1,0,0],[42,42,41,24,19,0],[15,10,15,2,1,0],[30,26,30,12,4,0],[21,21,19,12,4,0],[24,24,13,15,0,0],[8,7,1,8,0,0],[27,27,15,20,1,0],[15,12,15,6,1,0],[53,31,53,29,14,0],[59,59,55,38,23,0],[28,19,22,28,7,0],[53,53,19,12,10,0],[15,8,15,0,0,0],[20,20,19,10,6,0],[26,26,23,8,17,0],[43,43,21,11,0,0],[22,15,22,19,3,0],[22,22,7,1,0,0],[25,16,25,4,6,0],[23,18,23,6,1,0],[30,30,17,24,14,0],[23,23,19,10,2,0],[17,14,17,4,1,0],[44,13,44,21,3,0],[33,21,33,29,0,0],[23,23,19,19,4,0],[23,23,21,22,13,0],[11,7,11,0,0,0],[20,12,20,2,0,0],[21,21,14,11,4,0],[22,20,22,9,5,0],[24,15,24,6,0,0],[18,18,18,6,8,0],[11,9,11,3,0,0],[17,15,17,5,7,0],[34,12,34,0,0,0],[28,18,28,5,0,0],[13,10,13,0,0,0],[31,28,31,8,4,0],[14,12,14,4,0,0],[14,14,10,3,3,0],[19,15,19,15,0,0],[30,17,30,10,11,0],[28,14,28,2,0,0],[19,19,15,6,0,0],[15,15,15,1,2,0],[26,14,26,6,6,0],[26,17,26,6,0,0],[25,25,18,11,0,0],[24,13,24,0,0,0],[21,19,21,11,11,0],[8,8,3,5,0,0],[19,19,18,11,1,0],[30,15,30,4,0,0],[35,35,26,11,14,0],[28,13,28,7,0,0],[11,6,11,0,0,0],[10,9,10,1,4,0],[24,17,24,13,10,0],[27,20,27,10,1,0],[21,18,21,4,0,0],[23,23,18,5,4,0],[23,23,14,8,2,0],[41,41,16,7,0,0],[47,47,22,3,2,0],[22,21,22,7,0,0],[26,21,26,14,5,0],[18,16,18,8,0,0],[12,12,5,2,1,0],[25,13,25,3,0,0],[33,33,22,12,0,0],[23,15,23,6,5,0],[21,17,21,4,2,0],[15,15,14,2,0,0],[22,22,20,7,1,0],[22,22,17,3,4,0],[29,29,24,0,0,0],[24,15,24,4,1,0],[30,18,30,8,4,0],[13,13,10,0,5,0],[16,15,16,7,0,0],[23,23,22,12,0,0],[28,14,28,10,3,0],[24,18,24,6,1,0],[13,12,13,4,2,0],[20,18,13,3,20,0],[29,22,29,4,2,0],[28,19,28,15,2,0],[29,14,29,1,0,0],[19,16,19,2,6,0],[16,16,16,1,4,0],[45,45,19,9,0,0],[92,21,24,9,92,0],[60,47,36,23,60,0],[29,29,19,12,3,0],[18,18,13,8,3,0],[12,12,5,12,0,0],[6,2,0,6,6,0],[48,48,45,22,2,0],[20,20,16,7,0,0],[66,66,7,7,5,0],[81,81,20,26,14,0],[59,59,27,15,7,0],[60,60,41,12,9,0],[22,15,22,5,6,0],[19,19,7,5,0,0],[20,19,20,11,4,0],[30,28,17,30,9,0],[29,22,29,6,5,0],[66,66,46,47,8,0],[52,50,52,23,43,0],[32,32,29,7,0,0],[33,33,14,26,12,0],[19,17,19,12,7,0],[29,19,29,11,6,0],[8,8,7,0,0,0],[11,11,11,2,11,0],[28,22,28,5,1,0],[24,24,24,3,3,0],[24,24,18,2,1,0],[34,34,20,28,21,0],[20,20,8,5,8,0],[21,21,15,4,1,0],[24,24,19,16,3,0],[25,19,25,10,0,0],[37,23,37,15,6,0],[33,15,33,7,0,0],[19,19,8,6,0,0],[15,11,15,4,8,0],[27,19,27,9,3,0],[19,19,17,6,17,0],[27,27,15,8,9,0],[14,14,5,0,0,0],[15,13,15,0,0,0],[21,19,21,5,8,0],[20,15,20,6,2,0],[22,20,22,7,0,0],[32,32,23,19,6,0],[32,12,32,8,3,0],[18,18,13,5,5,0],[23,23,13,8,4,0],[29,25,29,4,3,0],[24,19,24,14,1,0],[24,19,24,5,6,0],[11,6,11,0,0,0],[22,14,22,3,1,0],[16,16,16,10,12,0],[32,17,32,3,1,0],[22,22,21,8,7,0],[25,17,25,11,1,0],[5,3,5,2,0,0],[24,18,12,4,24,0],[3,3,1,0,0,0],[19,19,15,11,8,0],[10,7,10,0,0,0],[22,19,22,4,2,0],[24,17,24,7,0,0],[25,16,25,5,0,0],[25,25,15,20,11,0],[21,21,21,8,5,0],[19,11,19,0,0,0],[17,13,17,4,1,0],[30,15,30,11,5,0],[23,22,23,11,1,0],[39,16,39,15,4,0],[17,6,17,0,0,0],[18,9,18,0,0,0],[18,15,18,12,3,0],[2,2,0,0,0,0],[37,29,37,21,0,0],[19,19,13,3,0,0],[24,17,24,13,1,0],[19,15,19,6,0,0],[16,16,15,9,0,0],[23,23,12,8,5,0],[23,17,23,10,6,0],[28,28,22,0,5,0],[19,7,19,0,0,0],[25,14,25,0,0,0],[23,18,23,5,2,0],[24,16,24,6,4,0],[23,19,23,13,2,0],[34,34,18,15,6,0],[13,13,5,11,1,0],[16,8,16,5,1,0],[28,13,28,10,4,0],[26,20,26,13,3,0],[25,25,21,16,11,0],[21,21,18,6,5,0],[4,4,0,0,0,0],[36,10,36,2,0,0],[58,45,58,6,3,0],[60,60,25,34,13,0],[50,20,21,50,19,0],[100,33,29,100,16,0],[56,56,31,16,13,0],[19,19,12,4,1,0],[24,24,15,9,9,0],[32,23,32,9,6,0],[43,43,36,30,11,0],[26,21,26,3,8,0],[22,22,22,6,7,0],[25,22,25,4,5,0],[21,21,17,14,8,0],[30,30,22,17,1,0],[28,19,28,7,0,0],[27,19,27,3,0,0],[18,18,15,10,0,0],[16,16,9,0,6,0],[26,13,26,4,0,0],[73,73,41,30,38,0],[28,28,22,23,4,0],[45,45,28,19,9,0],[91,91,30,43,4,0],[67,67,17,28,12,0],[72,72,66,34,29,0],[21,21,14,3,3,0],[25,25,18,4,1,0],[40,40,26,19,0,0],[10,10,10,7,0,0],[19,15,19,10,15,0],[28,16,28,3,3,0],[19,18,19,10,14,0],[33,33,29,10,13,0],[15,8,15,7,6,0],[17,11,17,6,12,0],[30,28,10,21,30,0],[35,24,23,35,6,0],[26,20,26,3,0,0],[10,10,7,8,0,0],[25,25,16,5,0,0],[20,20,15,10,5,0],[23,21,23,6,0,0],[22,18,22,13,0,0],[21,21,16,4,6,0],[17,17,14,8,0,0],[25,15,25,17,2,0],[27,18,27,6,1,0],[24,16,24,6,6,0],[26,21,26,11,3,0],[15,15,14,7,4,0],[18,18,13,6,2,0],[56,24,56,21,1,0],[100,20,100,23,15,0],[34,22,34,6,6,0],[24,18,24,12,0,0],[19,19,13,3,3,0],[24,24,9,2,5,0],[18,15,18,12,0,0],[26,26,14,1,11,0],[28,22,28,8,5,0],[25,19,25,6,7,0],[19,19,10,4,5,0],[15,10,15,4,3,0],[19,17,19,6,0,0],[29,17,29,9,3,0],[33,33,24,18,3,0],[28,21,28,8,0,0],[20,13,20,7,3,0],[6,6,5,4,2,0],[26,15,26,1,1,0],[30,15,30,0,0,0],[28,24,28,6,2,0],[23,23,22,14,8,0],[39,39,13,4,0,0],[30,14,12,30,9,0],[23,20,23,10,11,0],[22,22,21,1,12,0],[27,10,27,7,2,0],[19,16,19,7,5,0],[16,16,14,8,3,0],[21,21,5,5,0,0],[16,16,16,6,9,0],[20,19,17,20,0,0],[31,16,31,3,0,0],[14,14,13,8,8,0],[36,36,12,11,5,0],[14,14,10,7,0,0],[24,19,24,10,11,0],[21,21,21,16,2,0],[18,16,18,10,1,0],[13,13,11,6,0,0],[15,15,5,1,4,0],[22,22,14,14,4,0],[22,15,22,13,5,0],[23,21,23,7,5,0],[20,20,19,12,1,0],[11,6,6,11,0,0],[16,16,9,9,1,0],[21,17,21,6,3,0],[22,21,22,14,12,0],[45,45,27,5,5,0],[26,26,24,17,1,0],[30,8,30,14,1,0],[100,26,100,28,3,0],[57,57,33,31,26,0],[25,25,22,8,6,0],[30,30,26,14,10,0],[29,29,20,14,2,0],[19,13,19,1,0,0],[37,37,27,30,21,0],[21,14,21,9,0,0],[41,41,23,22,9,0],[25,25,21,7,3,0],[27,27,21,6,3,0],[17,17,16,11,3,0],[16,16,10,3,2,0],[22,22,16,14,1,0],[24,24,19,12,4,0],[18,18,15,11,4,0],[57,42,34,57,23,0],[29,29,16,5,3,0],[54,54,52,23,15,0],[36,30,36,5,2,0],[39,39,28,31,27,0],[43,27,43,16,21,0],[22,18,22,2,3,0],[17,17,15,1,1,0],[15,15,13,10,2,0],[27,27,17,8,0,0],[31,31,16,9,20,0],[16,16,16,7,0,0],[17,15,17,4,1,0],[18,13,18,4,0,0],[81,81,33,39,24,0],[74,74,20,24,12,0],[70,70,37,22,30,0],[19,19,1,0,0,0],[3,3,0,1,1,0],[40,18,40,0,0,0],[26,14,26,6,3,0],[34,27,34,13,5,0],[23,20,23,7,0,0],[20,10,20,5,0,0],[31,16,31,11,4,0],[51,23,51,17,2,0],[38,33,33,36,38,0],[20,20,14,12,0,0],[26,26,13,5,0,0],[10,10,10,4,3,0],[24,21,24,11,11,0],[28,16,28,0,0,0],[21,19,21,12,3,0],[66,57,66,27,12,0],[100,100,10,15,4,0],[84,84,30,27,5,0],[100,100,55,30,81,0],[100,100,37,34,97,0],[100,100,34,16,100,0],[100,100,47,35,100,0],[100,100,34,20,100,0],[100,100,45,37,96,0],[100,100,35,28,100,0],[100,100,38,49,100,0],[100,100,43,37,100,0],[100,100,44,25,100,0],[100,100,32,92,32,0],[100,100,78,70,27,0],[100,100,100,34,57,0],[100,100,81,27,32,0],[100,100,47,28,41,0],[100,100,29,46,69,0],[100,100,41,100,38,0],[100,100,41,100,39,0],[100,100,44,100,41,0],[100,100,56,100,42,0],[100,100,31,100,25,0],[100,100,35,74,59,0],[100,70,63,35,100,0],[100,39,100,76,61,0],[100,52,100,100,38,0],[100,38,100,100,39,0],[100,39,100,100,35,0],[100,35,100,78,53,0],[100,49,100,33,100,0],[100,36,100,71,65,0],[88,62,88,28,31,0],[100,24,100,29,10,0],[100,15,100,16,8,0],[60,58,60,34,11,0],[59,35,32,59,52,0],[100,71,100,48,50,0],[100,76,100,51,43,0],[78,62,78,32,50,0],[100,20,22,38,100,0],[87,63,87,56,18,0],[100,84,100,77,67,0],[62,62,50,39,23,0],[26,26,22,3,0,0],[18,18,16,8,1,0],[19,16,19,2,4,0],[39,39,28,12,0,0],[77,32,77,29,24,0],[24,23,24,13,22,0],[100,25,28,8,100,0],[37,37,31,22,33,0],[23,23,15,14,12,0],[60,60,35,16,11,0],[94,29,94,33,11,0]],"renderLoad":[[272,41],[288,80],[405,33],[1273,39],[1290,37],[1407,28],[2276,45],[2293,33],[2410,30],[3278,47],[3295,35],[3412,40],[4267,38],[4281,39],[4298,88],[4415,44],[4432,32],[5250,97],[5267,21],[5284,7],[5350,41],[5367,51],[5384,37],[6269,30],[6286,34],[6319,43],[6453,43],[7272,26],[7288,28],[7322,32],[7439,83],[7456,70],[8274,26],[8291,19],[8324,32],[8442,35],[9278,27],[9295,20],[9328,43],[9444,33],[10266,32],[10280,18],[10330,78],[10446,34],[11282,31],[11298,28],[11349,30],[11466,75],[12284,36],[12301,28],[12351,41],[12468,36],[12485,37],[13287,34],[13303,62]]}
--------------------------------------------------------------------------------
/dataset/workload/osborn/raw/README.md:
--------------------------------------------------------------------------------
1 | # 本文件夹负载序列原始数据说明
2 |
3 | ## 采集systrace
4 |
5 | 1. 配置手机的HMP和CPU调速器
6 | 1. `sched_boost` = 1
7 | 2. 大核心的CPU调速器 = `performance`
8 | 2. 开启设备的ADB
9 | 3. 点击[这里](https://developer.android.com/studio/releases/platform-tools)下载`platform-tools`,配置完成后执行
10 |
11 | ```bash
12 | python systrace.py -t 30 input idle view -o xxxxx.html
13 | ```
14 | ## 采集设备
15 |
16 | 坚果 Pro 2
17 | sdm660 A73 x 4 @2208mhz
18 | 同频性能:1638(A53为1024)
19 |
20 | ## 本文件夹采集的负载情景
21 |
22 | 每段大约30s
23 |
24 | - 微信 朋友圈
25 | - 微信 打字
26 | - 微信 选择图片
27 | - 微信 公众号
28 | - 微信 小程序
29 | - QQ 打字 滑动
30 | - QQ 空间动态
31 | - bili 信息流
32 | - bili 1080+弹幕
33 | - share 信息流
34 | - 贴吧 wp7吧
35 | - 酷安 首页
36 | - 美团 搜索饭店
37 | - via 浏览apple官网
38 | - 七日之都 1-1
39 | - 七日之都 小boss
40 | - 淘宝 选择小米移动电源
41 | - 闲鱼 搜索游戏主机
42 | - 百度地图 搜索世纪大道
43 | - Twitter 信息流
44 | - 频繁多任务切换
45 |
--------------------------------------------------------------------------------
/dataset/workload/osborn/raw/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "device": "坚果 Pro 2",
3 | "date": "2019-02-26T15:00:00.000Z",
4 | "efficiency": 1638,
5 | "freq": 2208,
6 | "onscreen": {
7 | "comment": "用于评估使用时性能和续航,在仿真器内会顺序执行,百度地图和微信小程序满负载比重太高,去除",
8 | "loadSeq": [
9 | "bili-danmu.html",
10 | "bili-feed.html",
11 | "coolapk-feed.html",
12 | "game-7days-city-boss.html",
13 | "game-7days-city-regular.html",
14 | "meituan-explore.html",
15 | "qq-chat.html",
16 | "qq-qzone.html",
17 | "share-feed.html",
18 | "taobao-international-explore.html",
19 | "task-switch.html",
20 | "tieba-lite.html",
21 | "twitter-feed.html",
22 | "via-iphonexs-intro.html",
23 | "wx-chat.html",
24 | "wx-gongzhonghao.html",
25 | "wx-moment.html",
26 | "wx-select-pic.html",
27 | "xianyu-search.html",
28 | "bili-download.html"
29 | ]
30 | },
31 | "offscreen": {
32 | "comment": "用于评估待机时续航,在仿真器内会顺序执行,注意需要bili-download.html先拉高负载再进入待机检查,来避免借助过高的above绕过待机耗电检查即使高频的targetload很低很难降频省电",
33 | "loadSeq": [
34 | "idle-music.html"
35 | ]
36 | }
37 | }
--------------------------------------------------------------------------------
/media/sim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yc9559/wipe-v2/14059cc82ca0527fe61d1cd0b1d2f9a2cff3b1be/media/sim.png
--------------------------------------------------------------------------------
/source/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "cpumodel.h"
6 | #include "dump.h"
7 | #include "json.hpp"
8 | #include "openga_helper.h"
9 | #include "sim.hpp"
10 | #include "workload.h"
11 |
12 | template
13 | void DoOpt(Soc &soc, const Workload &work, const Workload &idle) {
14 | auto nsga3_opt = OpengaAdapter(&soc, &work, &idle, "./conf.json");
15 | auto ret = nsga3_opt.Optimize();
16 | auto dumper = Dumper(soc, "./output/");
17 | dumper.DumpToTXT(ret);
18 | dumper.DumpToCSV(ret);
19 | dumper.DumpToShellScript(ret);
20 | dumper.DumpToUperfJson(ret);
21 | }
22 |
23 | int main() {
24 | nlohmann::json j;
25 | {
26 | std::ifstream ifs("./conf.json");
27 | if (!ifs.good()) {
28 | using namespace std;
29 | cout << "WIPE-v2 config file access ERROR: "
30 | << "./conf.json" << endl;
31 | throw std::runtime_error("file access error");
32 | }
33 | ifs >> j;
34 | }
35 |
36 | auto todo_models = j["todoModels"];
37 | auto workload = j["mergedWorkload"];
38 | auto idleload = j["idleWorkload"];
39 | auto use_uperf = j["useUperf"];
40 |
41 | Workload work(workload);
42 | Workload idle(idleload);
43 |
44 | for (const auto &model : todo_models) {
45 | Soc soc(model);
46 | if (use_uperf) {
47 | if (soc.GetSchedType() == Soc::kWalt) {
48 | DoOpt(soc, work, idle);
49 | }
50 | if (soc.GetSchedType() == Soc::kPelt) {
51 | DoOpt(soc, work, idle);
52 | }
53 | } else {
54 | if (soc.GetSchedType() == Soc::kWalt) {
55 | DoOpt(soc, work, idle);
56 | }
57 | if (soc.GetSchedType() == Soc::kPelt) {
58 | DoOpt(soc, work, idle);
59 | }
60 | }
61 | }
62 |
63 | return 0;
64 | }
65 |
--------------------------------------------------------------------------------
/source/opt/openga_helper.cpp:
--------------------------------------------------------------------------------
1 | #include "openga_helper.h"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "interactive.h"
8 | #include "json.hpp"
9 |
10 | template
11 | OpengaAdapter::OpengaAdapter(Soc *soc, const Workload *workload, const Workload *idleload,
12 | const std::string &ga_cfg_file)
13 | : soc_(soc), workload_(workload), idleload_(idleload) {
14 | ParseCfgFile(ga_cfg_file);
15 | InitDefaultScore();
16 | };
17 |
18 | template
19 | void OpengaAdapter::ParseCfgFile(const std::string &ga_cfg_file) {
20 | nlohmann::json j;
21 | {
22 | std::ifstream ifs(ga_cfg_file);
23 | if (!ifs.good()) {
24 | using namespace std;
25 | cout << "GA config file access ERROR: " << ga_cfg_file << endl;
26 | throw std::runtime_error("file access error");
27 | }
28 | ifs >> j;
29 | }
30 |
31 | // 解析NSGA3相关参数
32 | auto p = j["gaParameter"];
33 | ga_cfg_.population = p["population"];
34 | ga_cfg_.generation_max = p["generationMax"];
35 | ga_cfg_.crossover_fraction = p["crossoverFraction"];
36 | ga_cfg_.mutation_rate = p["mutationRate"];
37 | ga_cfg_.eta = p["eta"];
38 | ga_cfg_.thread_num = p["threadNum"];
39 | ga_cfg_.random_seed = p["randomSeed"];
40 |
41 | // 解析结果的分数限制和可调占比
42 | auto misc = j["miscSettings"];
43 | misc_.idle_fraction = misc["ga.cost.batteryScore.idleFraction"];
44 | misc_.work_fraction = misc["ga.cost.batteryScore.workFraction"];
45 | misc_.idle_lasting_min = misc["ga.cost.limit.idleLastingMin"];
46 | misc_.performance_max = misc["ga.cost.limit.performanceMax"];
47 |
48 | sim_misc_.working_base_mw = misc["sim.power.workingBase_mw"];
49 | sim_misc_.idle_base_mw = misc["sim.power.idleBase_mw"];
50 |
51 | rank_misc_.common_fraction = misc["eval.perf.commonFraction"];
52 | rank_misc_.render_fraction = misc["eval.perf.renderFraction"];
53 | rank_misc_.perf_partition_len = misc["eval.perf.partitionLen"];
54 | rank_misc_.batt_partition_len = misc["eval.power.partitionLen"];
55 | rank_misc_.seq_lag_l1 = misc["eval.perf.seqLagL1"];
56 | rank_misc_.seq_lag_l2 = misc["eval.perf.seqLagL2"];
57 | rank_misc_.seq_lag_max = misc["eval.perf.seqLagMax"];
58 | rank_misc_.seq_lag_l0_scale = misc["eval.perf.seqLagL0Scale"];
59 | rank_misc_.seq_lag_l1_scale = misc["eval.perf.seqLagL1Scale"];
60 | rank_misc_.seq_lag_l2_scale = misc["eval.perf.seqLagL2Scale"];
61 | rank_misc_.enough_penalty = misc["eval.perf.enoughPenalty"];
62 | rank_misc_.complexity_fraction = misc["eval.complexityFraction"];
63 |
64 | // 解析参数搜索空间范围
65 | ParamDescCfg desc_cfg;
66 |
67 | auto get_range = [j](const std::string &key) {
68 | ParamDescElement el;
69 | el.range_start = j["parameterRange"][key]["min"];
70 | el.range_end = j["parameterRange"][key]["max"];
71 | return el;
72 | };
73 |
74 | desc_cfg.above_hispeed_delay = get_range("above_hispeed_delay");
75 | desc_cfg.go_hispeed_load = get_range("go_hispeed_load");
76 | desc_cfg.max_freq_hysteresis = get_range("max_freq_hysteresis");
77 | desc_cfg.min_sample_time = get_range("min_sample_time");
78 | desc_cfg.target_loads = get_range("target_loads");
79 | desc_cfg.sched_downmigrate = get_range("sched_downmigrate");
80 | desc_cfg.sched_upmigrate = get_range("sched_upmigrate");
81 | desc_cfg.sched_ravg_hist_size = get_range("sched_ravg_hist_size");
82 | desc_cfg.sched_window_stats_policy = get_range("sched_window_stats_policy");
83 | desc_cfg.sched_boost = get_range("sched_boost");
84 | desc_cfg.timer_rate = get_range("timer_rate");
85 | desc_cfg.input_duration = get_range("input_duration");
86 | desc_cfg.load_avg_period_ms = get_range("load_avg_period_ms");
87 | desc_cfg.down_threshold = get_range("down_threshold");
88 | desc_cfg.up_threshold = get_range("up_threshold");
89 | desc_cfg.boost = get_range("boost");
90 |
91 | InitParamDesc(desc_cfg);
92 | }
93 |
94 | template
95 | void OpengaAdapter::InitParamSeq(ParamSeq &p, const RandomFunc &rnd01) {
96 | p.reserve(param_len_);
97 | for (int i = 0; i < param_len_; ++i) {
98 | p.push_back(rnd01());
99 | }
100 | }
101 |
102 | // mutPolynomialBounded
103 | // Polynomial mutation as implemented in original NSGA-II algorithm in C by Deb.
104 | template
105 | ParamSeq OpengaAdapter::Mutate(const ParamSeq &X_base, const RandomFunc &rnd01, double shrink_scale) {
106 | // 假设X1,X2等长
107 | const int size = X_base.size();
108 | const double eta = ga_cfg_.eta;
109 | const double eta_1 = eta + 1.0;
110 | const double mut_pow = 1.0 / eta_1;
111 | ParamSeq ret(size);
112 |
113 | for (int idx = 0; idx < size; ++idx) {
114 | if (rnd01() >= 0.5) {
115 | ret[idx] = X_base[idx];
116 | continue;
117 | }
118 |
119 | const double delta_1 = X_base[idx];
120 | const double delta_2 = 1.0 - X_base[idx];
121 | const double rnd = rnd01();
122 | double delta_q, val;
123 |
124 | if (rnd < 0.5) {
125 | val = 2.0 * rnd + (1.0 - 2.0 * rnd) * std::pow(1.0 - delta_1, eta_1);
126 | delta_q = std::pow(val, mut_pow) - 1.0;
127 | } else {
128 | val = 2.0 * (1.0 - rnd) + 2.0 * (rnd - 0.5) * std::pow(1.0 - delta_2, eta_1);
129 | delta_q = 1.0 - std::pow(val, mut_pow);
130 | }
131 |
132 | ret[idx] = std::min(std::max(X_base[idx] + delta_q, 0.0), 1.0);
133 | }
134 | return ret;
135 | }
136 |
137 | // cxSimulatedBinaryBounded
138 | // Executes a simulated binary crossover that modify in-place the input individuals. The simulated binary crossover
139 | // expects :term:`sequence` individuals of floating point numbers
140 | template
141 | ParamSeq OpengaAdapter::Crossover(const ParamSeq &X1, const ParamSeq &X2, const RandomFunc &rnd01) {
142 | // 假设X1,X2等长
143 | const int size = X1.size();
144 | const double eta = ga_cfg_.eta;
145 | const double eta_1 = eta + 1.0;
146 | ParamSeq ret(size);
147 |
148 | for (int idx = 0; idx < size; ++idx) {
149 | if (rnd01() >= 0.5) {
150 | ret[idx] = X1[idx];
151 | continue;
152 | }
153 | if (fabs(X1[idx] - X2[idx]) < 0.0) {
154 | ret[idx] = X2[idx];
155 | continue;
156 | }
157 |
158 | const double x1 = std::min(X1[idx], X2[idx]);
159 | const double x2 = std::max(X1[idx], X2[idx]);
160 | const double rnd = rnd01();
161 | const double x2_x1 = x2 - x1;
162 | double beta_q;
163 |
164 | double beta = 1.0 + (2.0 * x1 / x2_x1);
165 | double alpha = 2.0 - std::pow(beta, -eta_1);
166 | if (rnd <= 1.0 / alpha) {
167 | beta_q = std::pow(rnd * alpha, 1.0 / eta_1);
168 | } else {
169 | beta_q = std::pow(1.0 / (2.0 - rnd * alpha), 1.0 / eta_1);
170 | }
171 |
172 | double c1 = 0.5 * (x1 + x2 - beta_q * x2_x1);
173 |
174 | beta = 1.0 + (2.0 * (1.0 - x2) / x2_x1);
175 | alpha = 2.0 - std::pow(beta, -eta_1);
176 | if (rnd <= 1.0 / alpha) {
177 | beta_q = std::pow(rnd * alpha, 1.0 / eta_1);
178 | } else {
179 | beta_q = std::pow(1.0 / (2.0 - rnd * alpha), 1.0 / eta_1);
180 | }
181 |
182 | double c2 = 0.5 * (x1 + x2 + beta_q * x2_x1);
183 |
184 | c1 = std::min(std::max(c1, 0.0), 1.0);
185 | c2 = std::min(std::max(c2, 0.0), 1.0);
186 |
187 | if (rnd01() <= 0.5) {
188 | ret[idx] = c2;
189 | } else {
190 | ret[idx] = c1;
191 | }
192 | }
193 | return ret;
194 | }
195 |
196 | template
197 | void OpengaAdapter::MO_report_generation(int generation_number,
198 | const EA::GenerationType &last_generation,
199 | const std::vector & pareto_front) {
200 | return;
201 | }
202 |
203 | template
204 | bool OpengaAdapter::EvalParamSeq(const ParamSeq ¶m_seq, MiddleCost &result) {
205 | typename SimType::Tunables t = TranslateParamSeq(param_seq);
206 |
207 | SimResultPack rp;
208 | rp.onscreen.capacity.reserve(workload_->windowed_load_.size());
209 | rp.onscreen.power.reserve(workload_->windowed_load_.size());
210 |
211 | SimType sim(t, sim_misc_);
212 | sim.Run(*workload_, *idleload_, *soc_, &rp);
213 | Rank rank(default_score_, rank_misc_);
214 | auto score = rank.Eval(*workload_, *idleload_, rp, *soc_, false);
215 |
216 | result.c1 = score.performance;
217 | result.c2 = score.battery_life;
218 | result.c3 = score.idle_lasting;
219 |
220 | bool pass = (score.idle_lasting > misc_.idle_lasting_min) && (score.performance < misc_.performance_max);
221 | return pass;
222 | }
223 |
224 | template
225 | void OpengaAdapter::InitDefaultScore() {
226 | typename SimType::Tunables t = GenerateDefaultTunables();
227 | Rank::Score s = {1.0, 1.0, 1.0};
228 |
229 | SimResultPack rp;
230 | rp.onscreen.capacity.reserve(workload_->windowed_load_.size());
231 | rp.onscreen.power.reserve(workload_->windowed_load_.size());
232 |
233 | SimType sim(t, sim_misc_);
234 | sim.Run(*workload_, *idleload_, *soc_, &rp);
235 | Rank rank(s, rank_misc_);
236 | default_score_ = rank.Eval(*workload_, *idleload_, rp, *soc_, true);
237 | }
238 |
239 | template
240 | std::vector::Result> OpengaAdapter::Optimize(void) {
241 | using namespace std::placeholders;
242 | EA::Chronometer timer;
243 | timer.tic();
244 |
245 | GA_Type ga_obj(ga_cfg_.random_seed);
246 | ga_obj.problem_mode = EA::GA_MODE::NSGA_III;
247 | ga_obj.verbose = false;
248 | ga_obj.population = ga_cfg_.population;
249 | ga_obj.generation_max = ga_cfg_.generation_max;
250 | ga_obj.calculate_MO_objectives = std::bind(&OpengaAdapter::CalcMultiObjectives, this, _1);
251 | ga_obj.init_genes = std::bind(&OpengaAdapter::InitParamSeq, this, _1, _2);
252 | ga_obj.eval_solution = std::bind(&OpengaAdapter::EvalParamSeq, this, _1, _2);
253 | ga_obj.mutate = std::bind(&OpengaAdapter::Mutate, this, _1, _2, _3);
254 | ga_obj.crossover = std::bind(&OpengaAdapter::Crossover, this, _1, _2, _3);
255 | ga_obj.MO_report_generation = std::bind(&OpengaAdapter::MO_report_generation, this, _1, _2, _3);
256 | ga_obj.crossover_fraction = ga_cfg_.crossover_fraction;
257 | ga_obj.mutation_rate = ga_cfg_.mutation_rate;
258 | ga_obj.dynamic_threading = false;
259 | ga_obj.multi_threading = false;
260 | ga_obj.N_threads = ga_cfg_.thread_num;
261 | ga_obj.idle_delay_us = 1; // switch between threads quickly
262 |
263 | if (ga_cfg_.thread_num > 1) {
264 | ga_obj.multi_threading = true;
265 | ga_obj.dynamic_threading = true;
266 | }
267 |
268 | std::cout << "\nTarget: " << soc_->name_ << std::endl;
269 | std::cout << "Chromosome length: " << param_len_ << std::endl;
270 |
271 | ga_obj.solve();
272 |
273 | std::cout << "\nOptimized in " << timer.toc() << " seconds." << std::endl;
274 |
275 | std::vector ret;
276 | ret.reserve(ga_obj.last_generation.fronts[0].size());
277 | auto paretofront_indices = ga_obj.last_generation.fronts[0];
278 | for (const auto &i : paretofront_indices) {
279 | Result r;
280 | const auto &chromosome = ga_obj.last_generation.chromosomes[i];
281 | r.tunable = TranslateParamSeq(chromosome.genes);
282 | r.score.performance = chromosome.middle_costs.c1;
283 | r.score.battery_life = chromosome.middle_costs.c2;
284 | r.score.idle_lasting = chromosome.middle_costs.c3;
285 | ret.push_back(r);
286 | }
287 |
288 | return ret;
289 | }
290 |
291 | int Quantify(double ratio, const ParamDescElement &desc) {
292 | return (desc.range_start + std::round((desc.range_end - desc.range_start) * ratio));
293 | }
294 |
295 | int QuatFreqParam(double ratio, const Cluster &cluster, const ParamDescElement &desc) {
296 | return cluster.freq_floor_to_opp(Quantify(ratio, desc));
297 | }
298 |
299 | int QuatLoadParam(double ratio, const ParamDescElement &desc) {
300 | int target_load = Quantify(ratio, desc);
301 | // 减少targetload没必要的参数档位,降低参数复杂度
302 | // if (target_load > 15 && target_load < 85) {
303 | // target_load = target_load >> 2 << 2;
304 | // }
305 | return target_load;
306 | }
307 |
308 | int QuatLargeParam(double ratio, int step, const ParamDescElement &desc) {
309 | return (Quantify(ratio, desc) / step) * step;
310 | }
311 |
312 | template
313 | void DefineBlock(ParamDesc &desc, const ParamDescCfg &p, const Soc *soc) {
314 | return;
315 | }
316 |
317 | template
318 | T TranslateBlock(ParamSeq::const_iterator &it_seq, ParamDesc::const_iterator &it_desc, const Soc *soc) {
319 | return T();
320 | }
321 |
322 | template <>
323 | void DefineBlock>(ParamDesc &desc, const ParamDescCfg &p, const Soc *soc) {
324 | for (const auto &cluster : soc->clusters_) {
325 | ParamDescElement hispeed_freq_desc = {cluster.model_.min_freq, cluster.model_.max_freq};
326 | desc.push_back(hispeed_freq_desc);
327 | desc.push_back(p.go_hispeed_load);
328 | desc.push_back(p.min_sample_time);
329 | desc.push_back(p.max_freq_hysteresis);
330 |
331 | int n_opp = cluster.model_.opp_model.size();
332 | int n_above = std::min(ABOVE_DELAY_MAX_LEN, n_opp);
333 | int n_targetloads = std::min(TARGET_LOAD_MAX_LEN, n_opp);
334 |
335 | for (int i = 0; i < n_above; ++i) {
336 | desc.push_back(p.above_hispeed_delay);
337 | }
338 | for (int i = 0; i < n_targetloads; ++i) {
339 | desc.push_back(p.target_loads);
340 | }
341 | }
342 | }
343 |
344 | template <>
345 | GovernorTs TranslateBlock(ParamSeq::const_iterator &it_seq, ParamDesc::const_iterator &it_desc,
346 | const Soc *soc) {
347 | GovernorTs t;
348 |
349 | int idx = 0;
350 | for (const auto &cluster : soc->clusters_) {
351 | t.t[idx].hispeed_freq = QuatFreqParam(*it_seq++, cluster, *it_desc++);
352 | t.t[idx].go_hispeed_load = QuatLoadParam(*it_seq++, *it_desc++);
353 | t.t[idx].min_sample_time = Quantify(*it_seq++, *it_desc++);
354 | t.t[idx].max_freq_hysteresis = Quantify(*it_seq++, *it_desc++);
355 |
356 | int n_opp = cluster.model_.opp_model.size();
357 | int n_above = std::min(ABOVE_DELAY_MAX_LEN, n_opp);
358 | int n_targetloads = std::min(TARGET_LOAD_MAX_LEN, n_opp);
359 |
360 | for (int i = 0; i < n_above; ++i) {
361 | t.t[idx].above_hispeed_delay[i] = Quantify(*it_seq++, *it_desc++);
362 | }
363 | for (int i = 0; i < n_targetloads; ++i) {
364 | t.t[idx].target_loads[i] = QuatLoadParam(*it_seq++, *it_desc++);
365 | }
366 | idx++;
367 | }
368 |
369 | // 时长类参数取整到一个timer_rate
370 | idx = 0;
371 | for (const auto &cluster : soc->clusters_) {
372 | auto & tunable = t.t[idx];
373 | double timer_quantum = 2; // timer_rate 固定为20ms
374 |
375 | tunable.min_sample_time = std::max(1.0, std::round(tunable.min_sample_time / timer_quantum));
376 | tunable.max_freq_hysteresis = std::max(1.0, std::round(tunable.max_freq_hysteresis / timer_quantum));
377 |
378 | int n_opp = cluster.model_.opp_model.size();
379 | int n_above = std::min(ABOVE_DELAY_MAX_LEN, n_opp);
380 |
381 | for (int i = 0; i < n_above; ++i) {
382 | tunable.above_hispeed_delay[i] = std::max(1.0, std::round(tunable.above_hispeed_delay[i] / timer_quantum));
383 | }
384 | idx++;
385 | }
386 |
387 | return std::move(t);
388 | }
389 |
390 | template <>
391 | void DefineBlock(ParamDesc &desc, const ParamDescCfg &p, const Soc *soc) {
392 | desc.push_back(p.sched_downmigrate);
393 | desc.push_back(p.sched_upmigrate);
394 | desc.push_back(p.sched_ravg_hist_size);
395 | desc.push_back(p.sched_window_stats_policy);
396 | desc.push_back(p.sched_boost);
397 | desc.push_back(p.timer_rate);
398 | }
399 |
400 | template <>
401 | WaltHmp::Tunables TranslateBlock(ParamSeq::const_iterator &it_seq, ParamDesc::const_iterator &it_desc, const Soc *soc) {
402 | WaltHmp::Tunables t;
403 | t.sched_downmigrate = QuatLoadParam(*it_seq++, *it_desc++);
404 | t.sched_upmigrate = QuatLoadParam(*it_seq++, *it_desc++);
405 | t.sched_upmigrate = std::max(t.sched_downmigrate, t.sched_upmigrate);
406 | t.sched_ravg_hist_size = Quantify(*it_seq++, *it_desc++);
407 | t.sched_window_stats_policy = Quantify(*it_seq++, *it_desc++);
408 | t.sched_boost = Quantify(*it_seq++, *it_desc++);
409 | t.timer_rate = Quantify(*it_seq++, *it_desc++);
410 | // sdm625和sdm820使用平衡型负载迁移
411 | if (soc->clusters_.size() < 2 || soc->clusters_[soc->GetLittleClusterIdx()].model_.core_num == 2) {
412 | t.sched_downmigrate = 45;
413 | t.sched_upmigrate = 45;
414 | }
415 | return std::move(t);
416 | }
417 |
418 | template <>
419 | void DefineBlock(ParamDesc &desc, const ParamDescCfg &p, const Soc *soc) {
420 | desc.push_back(p.down_threshold);
421 | desc.push_back(p.up_threshold);
422 | desc.push_back(p.load_avg_period_ms);
423 | desc.push_back(p.boost);
424 | desc.push_back(p.timer_rate);
425 | }
426 |
427 | template <>
428 | PeltHmp::Tunables TranslateBlock(ParamSeq::const_iterator &it_seq, ParamDesc::const_iterator &it_desc, const Soc *soc) {
429 | PeltHmp::Tunables t;
430 | t.down_threshold = Quantify(*it_seq++, *it_desc++);
431 | t.up_threshold = Quantify(*it_seq++, *it_desc++);
432 | t.up_threshold = std::max(t.down_threshold, t.up_threshold);
433 | t.load_avg_period_ms = Quantify(*it_seq++, *it_desc++);
434 | t.boost = Quantify(*it_seq++, *it_desc++);
435 | t.timer_rate = Quantify(*it_seq++, *it_desc++);
436 | return std::move(t);
437 | }
438 |
439 | template <>
440 | void DefineBlock(ParamDesc &desc, const ParamDescCfg &p, const Soc *soc) {
441 | for (const auto &cluster : soc->clusters_) {
442 | ParamDescElement input_freq = {cluster.model_.min_freq, cluster.model_.max_freq};
443 | desc.push_back(input_freq);
444 | }
445 | desc.push_back(p.input_duration);
446 | }
447 |
448 | template <>
449 | InputBoostWalt::Tunables TranslateBlock(ParamSeq::const_iterator &it_seq, ParamDesc::const_iterator &it_desc,
450 | const Soc *soc) {
451 | InputBoostWalt::Tunables t;
452 |
453 | int idx = 0;
454 | for (const auto &cluster : soc->clusters_)
455 | t.boost_freq[idx++] = QuatFreqParam(*it_seq++, cluster, *it_desc++);
456 | t.duration_quantum = QuatLargeParam(*it_seq++, 10, *it_desc++);
457 |
458 | return std::move(t);
459 | }
460 |
461 | template <>
462 | void DefineBlock(ParamDesc &desc, const ParamDescCfg &p, const Soc *soc) {
463 | for (const auto &cluster : soc->clusters_) {
464 | ParamDescElement input_freq = {cluster.model_.min_freq, cluster.model_.max_freq};
465 | desc.push_back(input_freq);
466 | }
467 | desc.push_back(p.input_duration);
468 | }
469 |
470 | template <>
471 | InputBoostPelt::Tunables TranslateBlock(ParamSeq::const_iterator &it_seq, ParamDesc::const_iterator &it_desc,
472 | const Soc *soc) {
473 | InputBoostPelt::Tunables t;
474 |
475 | int idx = 0;
476 | for (const auto &cluster : soc->clusters_)
477 | t.boost_freq[idx++] = QuatFreqParam(*it_seq++, cluster, *it_desc++);
478 | t.duration_quantum = QuatLargeParam(*it_seq++, 10, *it_desc++);
479 |
480 | return std::move(t);
481 | }
482 |
483 | template <>
484 | void DefineBlock(ParamDesc &desc, const ParamDescCfg &p, const Soc *soc) {
485 | for (const auto &cluster : soc->clusters_) {
486 | // 最大频率不能限制太多,否则影响突发性能,选择0.7*最大主频和1.2g较高的值
487 | int max_freq_floor = 0.7 * cluster.model_.max_freq;
488 | max_freq_floor = std::min(std::max(1200, max_freq_floor), cluster.model_.max_freq);
489 | auto min_range = ParamDescElement{cluster.model_.min_freq, cluster.model_.max_freq};
490 | auto max_range = ParamDescElement{max_freq_floor, cluster.model_.max_freq};
491 | desc.push_back(min_range);
492 | desc.push_back(max_range);
493 | }
494 | desc.push_back(p.sched_downmigrate);
495 | desc.push_back(p.sched_upmigrate);
496 | // DefineBlock>(desc, p, soc);
497 | }
498 |
499 | template <>
500 | UperfBoostWalt::Tunables TranslateBlock(ParamSeq::const_iterator &it_seq, ParamDesc::const_iterator &it_desc,
501 | const Soc *soc) {
502 | UperfBoostWalt::Tunables t;
503 |
504 | int idx = 0;
505 | for (const auto &cluster : soc->clusters_) {
506 | t.min_freq[idx] = QuatFreqParam(*it_seq++, cluster, *it_desc++);
507 | t.max_freq[idx] = QuatFreqParam(*it_seq++, cluster, *it_desc++);
508 | t.max_freq[idx] = std::max(t.min_freq[idx], t.max_freq[idx]);
509 | ++idx;
510 | }
511 | t.sched_down = Quantify(*it_seq++, *it_desc++);
512 | t.sched_up = Quantify(*it_seq++, *it_desc++);
513 | t.sched_up = std::max(t.sched_down, t.sched_up);
514 | // auto iblk = TranslateBlock>(it_seq, it_desc, soc);
515 | // t.little = iblk.t[soc->GetLittleClusterIdx()];
516 | // t.big = iblk.t[soc->GetBigClusterIdx()];
517 | t.enabled = true;
518 |
519 | return std::move(t);
520 | }
521 |
522 | template <>
523 | void DefineBlock(ParamDesc &desc, const ParamDescCfg &p, const Soc *soc) {
524 | for (const auto &cluster : soc->clusters_) {
525 | // 最大频率不能限制太多,否则影响突发性能,选择0.66*最大主频和1.2g较高的值
526 | int max_freq_floor = 0.66 * cluster.model_.max_freq;
527 | max_freq_floor = std::min(std::max(1200, max_freq_floor), cluster.model_.max_freq);
528 | auto min_range = ParamDescElement{cluster.model_.min_freq, cluster.model_.max_freq};
529 | auto max_range = ParamDescElement{max_freq_floor, cluster.model_.max_freq};
530 | desc.push_back(min_range);
531 | desc.push_back(max_range);
532 | }
533 | desc.push_back(p.down_threshold);
534 | desc.push_back(p.up_threshold);
535 | // DefineBlock>(desc, p, soc);
536 | }
537 |
538 | template <>
539 | UperfBoostPelt::Tunables TranslateBlock(ParamSeq::const_iterator &it_seq, ParamDesc::const_iterator &it_desc,
540 | const Soc *soc) {
541 | UperfBoostPelt::Tunables t;
542 |
543 | int idx = 0;
544 | for (const auto &cluster : soc->clusters_) {
545 | t.min_freq[idx] = QuatFreqParam(*it_seq++, cluster, *it_desc++);
546 | t.max_freq[idx] = QuatFreqParam(*it_seq++, cluster, *it_desc++);
547 | t.max_freq[idx] = std::max(t.min_freq[idx], t.max_freq[idx]);
548 | ++idx;
549 | }
550 | t.sched_down = Quantify(*it_seq++, *it_desc++);
551 | t.sched_up = Quantify(*it_seq++, *it_desc++);
552 | t.sched_up = std::max(t.sched_down, t.sched_up);
553 | // auto iblk = TranslateBlock>(it_seq, it_desc, soc);
554 | // t.little = iblk.t[soc->GetLittleClusterIdx()];
555 | // t.big = iblk.t[soc->GetBigClusterIdx()];
556 | t.enabled = true;
557 |
558 | return std::move(t);
559 | }
560 |
561 | template
562 | bool IsSupportBoost(const Soc *soc) {
563 | return false;
564 | }
565 |
566 | template <>
567 | bool IsSupportBoost(const Soc *soc) {
568 | return soc->GetInputBoostFeature();
569 | }
570 |
571 | template <>
572 | bool IsSupportBoost(const Soc *soc) {
573 | return soc->GetInputBoostFeature();
574 | }
575 |
576 | template <>
577 | bool IsSupportBoost(const Soc *soc) {
578 | return true;
579 | }
580 |
581 | template <>
582 | bool IsSupportBoost(const Soc *soc) {
583 | return true;
584 | }
585 |
586 | template
587 | typename SimType::Tunables OpengaAdapter::TranslateParamSeq(const ParamSeq &p) const {
588 | typename SimType::Tunables t;
589 |
590 | ParamSeq::const_iterator it_seq = p.begin();
591 | ParamDesc::const_iterator it_desc = param_desc_.begin();
592 | // cpufreq调速器参数上下限
593 | t.governor = TranslateBlock>(it_seq, it_desc, soc_);
594 | // sched任务调度器参数上下限
595 | t.sched = TranslateBlock(it_seq, it_desc, soc_);
596 | // 是否启用boost
597 | t.has_boost = IsSupportBoost(soc_);
598 | if (t.has_boost) {
599 | // boost升频参数上下限
600 | t.boost = TranslateBlock(it_seq, it_desc, soc_);
601 | }
602 | return t;
603 | }
604 |
605 | template
606 | void OpengaAdapter::InitParamDesc(const ParamDescCfg &p) {
607 | // cpufreq调速器参数上下限
608 | DefineBlock>(param_desc_, p, soc_);
609 | // sched任务调度器参数上下限
610 | DefineBlock(param_desc_, p, soc_);
611 | // 是否启用boost
612 | if (IsSupportBoost(soc_)) {
613 | // boost升频参数上下限
614 | DefineBlock(param_desc_, p, soc_);
615 | }
616 | param_len_ = param_desc_.size();
617 | }
618 |
619 | template
620 | typename SimType::Tunables OpengaAdapter::GenerateDefaultTunables(void) const {
621 | typename SimType::Tunables t;
622 | // cpufreq调速器参数上下限
623 | int idx = 0;
624 | for (const auto &cluster : soc_->clusters_)
625 | t.governor.t[idx++] = typename SimType::Governor::Tunables(cluster);
626 | // sched任务调度器参数上下限
627 | t.sched = typename SimType::Sched::Tunables();
628 | // 是否启用boost
629 | if (IsSupportBoost(soc_)) {
630 | // boost升频参数上下限
631 | t.boost = typename SimType::Boost::Tunables(soc_);
632 | }
633 | return t;
634 | }
635 |
636 | template class OpengaAdapter;
637 | template class OpengaAdapter;
638 | template class OpengaAdapter;
639 | template class OpengaAdapter;
640 |
--------------------------------------------------------------------------------
/source/opt/openga_helper.h:
--------------------------------------------------------------------------------
1 | #ifndef __OPENGA_HELPER_H
2 | #define __OPENGA_HELPER_H
3 |
4 | #include
5 | #include
6 |
7 | #include "cpumodel.h"
8 | #include "hmp_pelt.h"
9 | #include "hmp_walt.h"
10 | #include "input_boost.h"
11 | #include "interactive.h"
12 | #include "openga.hpp"
13 | #include "rank.h"
14 | #include "sim.hpp"
15 | #include "sim_types.h"
16 | #include "workload.h"
17 |
18 | using InputBoostWalt = InputBoost;
19 | using InputBoostPelt = InputBoost;
20 | using UperfBoostWalt = UperfBoost;
21 | using UperfBoostPelt = UperfBoost;
22 |
23 | using SimQcomBL = Sim;
24 | using SimBL = Sim;
25 | using SimQcomUp = Sim;
26 | using SimUp = Sim;
27 |
28 | typedef struct _ParamDescElement {
29 | int range_start;
30 | int range_end;
31 | } ParamDescElement;
32 |
33 | typedef struct _ParamDescCfg {
34 | ParamDescElement above_hispeed_delay;
35 | ParamDescElement go_hispeed_load;
36 | ParamDescElement max_freq_hysteresis;
37 | ParamDescElement min_sample_time;
38 | ParamDescElement target_loads;
39 | ParamDescElement sched_downmigrate;
40 | ParamDescElement sched_upmigrate;
41 | ParamDescElement sched_ravg_hist_size;
42 | ParamDescElement sched_window_stats_policy;
43 | ParamDescElement sched_boost;
44 | ParamDescElement timer_rate;
45 | ParamDescElement input_duration;
46 | ParamDescElement load_avg_period_ms;
47 | ParamDescElement down_threshold;
48 | ParamDescElement up_threshold;
49 | ParamDescElement boost;
50 | } ParamDescCfg;
51 |
52 | using ParamSeq = std::vector;
53 | using ParamDesc = std::vector;
54 |
55 | template
56 | class OpengaAdapter {
57 | public:
58 | typedef struct _GaCfg {
59 | int population;
60 | int generation_max;
61 | float crossover_fraction;
62 | float mutation_rate;
63 | float eta;
64 | int thread_num;
65 | uint64_t random_seed;
66 | } GaCfg;
67 |
68 | typedef struct _MiscConst {
69 | double idle_fraction;
70 | double work_fraction;
71 | double idle_lasting_min;
72 | double performance_max;
73 | } MiscConst;
74 |
75 | typedef struct _MiddleCost {
76 | double c1;
77 | double c2;
78 | double c3;
79 | } MiddleCost;
80 |
81 | struct Result {
82 | typename SimType::Tunables tunable;
83 | Rank::Score score;
84 | };
85 |
86 | using GA_Type = EA::Genetic;
87 | using RandomFunc = std::function;
88 |
89 | OpengaAdapter(Soc *soc, const Workload *workload, const Workload *idleload, const std::string &ga_cfg_file);
90 | std::vector Optimize(void);
91 |
92 | private:
93 | OpengaAdapter();
94 | std::vector CalcMultiObjectives(const typename GA_Type::thisChromosomeType &X) {
95 | // result.c1 = score.performance; // 卡顿程度,越小越好
96 | // result.c2 = score.battery_life; // 亮屏续航,越大越好
97 | // result.c3 = score.idle_lasting // 灭屏待机,越大越好
98 | return {X.middle_costs.c1,
99 | -(misc_.work_fraction * X.middle_costs.c2 + misc_.idle_fraction * X.middle_costs.c3)};
100 | }
101 |
102 | ParamSeq Mutate(const ParamSeq &X_base, const RandomFunc &rnd01, double shrink_scale);
103 | ParamSeq Crossover(const ParamSeq &X1, const ParamSeq &X2, const RandomFunc &rnd01);
104 |
105 | typename SimType::Tunables TranslateParamSeq(const ParamSeq &p) const;
106 | typename SimType::Tunables GenerateDefaultTunables(void) const;
107 | void InitParamDesc(const ParamDescCfg &p);
108 |
109 | void MO_report_generation(int generation_number, const EA::GenerationType &last_generation,
110 | const std::vector &pareto_front);
111 |
112 | void InitParamSeq(ParamSeq &p, const RandomFunc &rnd01);
113 | bool EvalParamSeq(const ParamSeq ¶m_seq, MiddleCost &result);
114 | void InitDefaultScore();
115 | void InitDefaultPowersum();
116 | void ParseCfgFile(const std::string &ga_cfg_file);
117 |
118 | Soc * soc_;
119 | const Workload *workload_;
120 | const Workload *idleload_;
121 | Rank::Score default_score_;
122 | int param_len_;
123 | ParamDesc param_desc_;
124 | GaCfg ga_cfg_;
125 | MiscConst misc_;
126 |
127 | typename SimType::MiscConst sim_misc_;
128 | Rank::MiscConst rank_misc_;
129 | };
130 |
131 | #endif
132 |
--------------------------------------------------------------------------------
/source/output/dump.h:
--------------------------------------------------------------------------------
1 | #ifndef __DUMP_H
2 | #define __DUMP_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include "cpumodel.h"
8 | #include "openga_helper.h"
9 | #include "sim.hpp"
10 |
11 | template
12 | class Dumper {
13 | #define PERF_LEVEL_NUM 7
14 | public:
15 | using OpengaResults = std::vector::Result>;
16 |
17 | Dumper() = delete;
18 | Dumper(const Soc &soc, const std::string &output_path) : soc_(soc), output_path_(output_path){};
19 | void DumpToTXT(const OpengaResults &results) const;
20 | void DumpToCSV(const OpengaResults &results) const;
21 | void DumpToShellScript(const OpengaResults &results);
22 | void DumpToUperfJson(const OpengaResults &results) const;
23 |
24 | private:
25 | std::string SimTunableToStr(const typename SimType::Tunables &t) const;
26 | std::string LevelToStr(const typename SimType::Tunables &t, int level) const;
27 | std::string SysfsObjToStr(void);
28 |
29 | const Soc soc_;
30 | const std::string output_path_;
31 |
32 | int n_param_;
33 | };
34 |
35 | #endif
36 |
--------------------------------------------------------------------------------
/source/sim/cpumodel.cpp:
--------------------------------------------------------------------------------
1 | #include "cpumodel.h"
2 |
3 | #include
4 | #include
5 |
6 | #include "json.hpp"
7 |
8 | Cluster::Cluster(Model model) : model_(model) {
9 | busy_pct_ = 0;
10 | SetMinfreq(model.min_freq);
11 | SetMaxfreq(model.max_freq);
12 | SetCurfreq(model.max_freq);
13 | }
14 |
15 | Soc::Soc(const std::string &model_file) {
16 | std::ifstream ifs(model_file);
17 | nlohmann::json j;
18 | ifs >> j;
19 |
20 | // SOC的型号
21 | name_ = j["name"];
22 |
23 | // 提供的容量大于SOC最大容量xx%的跳过卡顿判断
24 | enough_capacity_pct_ = j["enoughCapacityPct"];
25 |
26 | // 使用的调度器类型
27 | if (j["sched"] == "walt")
28 | sched_type_ = kWalt;
29 | else if (j["sched"] == "pelt")
30 | sched_type_ = kPelt;
31 | else
32 | sched_type_ = kLegacy;
33 |
34 | // 多核心模式
35 | if (j["intra"] == "asmp")
36 | intra_type_ = kASMP;
37 | else
38 | intra_type_ = kSMP;
39 |
40 | // 是否支持输入升频
41 | input_boost_ = j["inputBoost"];
42 |
43 | // 频点与功耗
44 | for (const auto &it : j["cluster"]) {
45 | Cluster::Model m;
46 | m.core_num = it["coreNum"];
47 | m.efficiency = it["efficiency"];
48 | m.min_freq = it["minFreq"];
49 | m.max_freq = it["maxFreq"];
50 | m.opp_model.reserve(it["opp"].size());
51 | for (uint32_t i = 0; i < it["opp"].size(); ++i) {
52 | m.opp_model.push_back({it["opp"][i], it["corePower"][i], it["clusterPower"][i]});
53 | }
54 | clusters_.push_back(Cluster(m));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/source/sim/cpumodel.h:
--------------------------------------------------------------------------------
1 | #ifndef __CPU_MODEL_H
2 | #define __CPU_MODEL_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | class Cluster {
10 | public:
11 | typedef struct _Pwr {
12 | int16_t freq;
13 | int16_t core_power;
14 | int16_t cluster_power;
15 | } Pwr;
16 |
17 | typedef struct _ClusterModel {
18 | int min_freq;
19 | int max_freq;
20 | int efficiency;
21 | int core_num;
22 | std::vector opp_model;
23 | } Model;
24 |
25 | Cluster(Model model);
26 | int FindFreqIdx(int freq, int left, int right) const;
27 | int freq_floor_to_idx(int freq) const;
28 | int freq_ceiling_to_idx(int freq) const;
29 | int freq_floor_to_opp(int freq) const;
30 | int freq_ceiling_to_opp(int freq) const;
31 | int CalcPower(const int *load_pcts) const;
32 | int CalcCapacity(void) const;
33 | int GetBusyPct(void) const { return busy_pct_; }
34 | int GetMinfreq(void) const { return min_freq_; }
35 | int GetMaxfreq(void) const { return max_freq_; }
36 | int GetCurfreq(void) const { return cur_freq_; }
37 | int GetOpp(int idx) const { return model_.opp_model[idx].freq; }
38 | void SetBusyPct(int load) { busy_pct_ = load; }
39 | void SetMinfreq(int freq);
40 | void SetMaxfreq(int freq);
41 | void SetCurfreq(int freq);
42 |
43 | const Model model_;
44 |
45 | private:
46 | Cluster();
47 |
48 | int busy_pct_;
49 | int min_freq_;
50 | int max_freq_;
51 | int cur_freq_;
52 | int min_opp_idx_;
53 | int max_opp_idx_;
54 | int cur_opp_idx_;
55 | };
56 |
57 | // 在给定下标闭区间内,找到 >=@freq的最低频点对应的opp频点序号
58 | inline int Cluster::FindFreqIdx(int freq, int left, int right) const {
59 | left = (left == -1) ? 0 : left;
60 | right = (right == -1) ? (model_.opp_model.size() - 1) : right;
61 | int i = left;
62 | // 第1-n个频点,到达第n或者当前频点>=要寻找的即可跳出
63 | for (; i < right && GetOpp(i) < freq; ++i)
64 | ;
65 | return i;
66 | }
67 |
68 | // 在最低最高频率范围内,找到 >=@freq的最低频点对应的opp频点序号
69 | inline int Cluster::freq_floor_to_idx(int freq) const {
70 | return FindFreqIdx(freq, min_opp_idx_, max_opp_idx_);
71 | }
72 |
73 | // 在最低最高频率范围内,找到 <=@freq的最大频点对应的opp频点序号
74 | inline int Cluster::freq_ceiling_to_idx(int freq) const {
75 | int i = FindFreqIdx(freq, min_opp_idx_, max_opp_idx_);
76 | return (i > 0 && GetOpp(i) > freq) ? (i - 1) : i;
77 | }
78 |
79 | // 在最低最高频率范围内,找到 >=@freq的最低频点
80 | inline int Cluster::freq_floor_to_opp(int freq) const {
81 | return GetOpp(freq_floor_to_idx(freq));
82 | }
83 |
84 | // 在最低最高频率范围内,找到 <=@freq的最大频点
85 | inline int Cluster::freq_ceiling_to_opp(int freq) const {
86 | return GetOpp(freq_ceiling_to_idx(freq));
87 | }
88 |
89 | inline void Cluster::SetMinfreq(int freq) {
90 | min_opp_idx_ = FindFreqIdx(freq, -1, -1);
91 | min_freq_ = GetOpp(min_opp_idx_);
92 | if (cur_freq_ < min_freq_)
93 | SetCurfreq(min_freq_);
94 | }
95 |
96 | inline void Cluster::SetMaxfreq(int freq) {
97 | max_opp_idx_ = FindFreqIdx(freq, -1, -1);
98 | max_freq_ = GetOpp(max_opp_idx_);
99 | if (cur_freq_ > max_freq_)
100 | SetCurfreq(max_freq_);
101 | }
102 |
103 | inline void Cluster::SetCurfreq(int freq) {
104 | cur_opp_idx_ = freq_floor_to_idx(freq);
105 | cur_freq_ = GetOpp(cur_opp_idx_);
106 | }
107 |
108 | // 耗电量 = 功耗(mw) * 占用率(最大100)
109 | inline int Cluster::CalcPower(const int *load_pcts) const {
110 | int pwr = model_.opp_model[cur_opp_idx_].cluster_power * 100;
111 | int core_pwr = model_.opp_model[cur_opp_idx_].core_power;
112 | for (int i = 0; i < model_.core_num; ++i) {
113 | pwr += core_pwr * load_pcts[i];
114 | }
115 | return pwr;
116 | }
117 |
118 | inline int Cluster::CalcCapacity() const {
119 | return (cur_freq_ * model_.efficiency * 100);
120 | }
121 |
122 | class Soc {
123 | public:
124 | // 多核心模式
125 | typedef enum _IntraType { kSMP = 0, kASMP } IntraType;
126 | // 使用的调度器类型
127 | typedef enum _SchedType { kLegacy = 0, kWalt, kPelt } SchedType;
128 |
129 | Soc(const std::string &model_file);
130 | ~Soc(){};
131 |
132 | IntraType GetIntraType(void) const { return intra_type_; }
133 | SchedType GetSchedType(void) const { return sched_type_; }
134 | bool GetInputBoostFeature(void) const { return input_boost_; }
135 |
136 | int GetLittleClusterIdx(void) const { return 0; }
137 | int GetBigClusterIdx(void) const { return clusters_.size() - 1; }
138 |
139 | int GetEnoughCapacity(void) const {
140 | return (clusters_.back().model_.max_freq * clusters_.back().model_.efficiency * enough_capacity_pct_);
141 | }
142 |
143 | int GetMaxCapacity(void) const {
144 | return (clusters_.back().model_.max_freq * clusters_.back().model_.efficiency * 98);
145 | }
146 |
147 | std::string name_;
148 | std::vector clusters_;
149 |
150 | private:
151 | Soc();
152 |
153 | IntraType intra_type_;
154 | SchedType sched_type_;
155 | bool input_boost_;
156 | int enough_capacity_pct_; // 提供的容量大于SOC最大容量xx%的跳过卡顿判断
157 | };
158 |
159 | #endif
160 |
--------------------------------------------------------------------------------
/source/sim/hmp.h:
--------------------------------------------------------------------------------
1 | #ifndef __HMP_H
2 | #define __HMP_H
3 |
4 | #include
5 |
6 | #include "cpumodel.h"
7 | #include "interactive.h"
8 |
9 | class Hmp {
10 | public:
11 | struct HmpTunables {};
12 |
13 | struct HmpCfg {
14 | Cluster * little;
15 | Cluster * big;
16 | Interactive *governor_little;
17 | Interactive *governor_big;
18 | };
19 |
20 | Hmp(){};
21 | Hmp(HmpCfg cfg)
22 | : little_(cfg.little),
23 | big_(cfg.big),
24 | active_(big_),
25 | idle_(little_),
26 | governor_little_(cfg.governor_little),
27 | governor_big_(cfg.governor_big),
28 | up_demand_thd_(0),
29 | down_demand_thd_(0) {
30 | cluster_num_ = (big_ == little_) ? 1 : 2;
31 | }
32 |
33 | int SchedulerTick(int max_load, const int *loads, int n_load, int now) { return 0; };
34 | int CalcPower(const int *loads) const;
35 | int CalcPowerForIdle(const int *loads) const;
36 |
37 | protected:
38 | #define NLoadsMax 4
39 | int LoadToBusyPct(const Cluster *c, uint64_t load) const;
40 |
41 | Cluster * little_;
42 | Cluster * big_;
43 | Cluster * active_;
44 | Cluster * idle_;
45 | Interactive *governor_little_;
46 | Interactive *governor_big_;
47 | int cluster_num_;
48 | uint64_t up_demand_thd_;
49 | uint64_t down_demand_thd_;
50 | };
51 |
52 | inline int Hmp::LoadToBusyPct(const Cluster *c, uint64_t load) const {
53 | return (load / (c->GetCurfreq() * c->model_.efficiency));
54 | }
55 |
56 | // 外层保证已执行adaptload,负载百分比不超过100%
57 | // loads: freq * busy_pct * efficiency
58 | inline int Hmp::CalcPower(const int *loads) const {
59 | const int idle_load_pcts[] = {1, 0, 0, 0};
60 | int load_pcts[NLoadsMax];
61 | for (int i = 0; i < NLoadsMax; ++i) {
62 | load_pcts[i] = loads[i] / (active_->model_.efficiency * active_->GetCurfreq());
63 | }
64 |
65 | int pwr = 0;
66 | pwr += active_->CalcPower(load_pcts);
67 | pwr += idle_->CalcPower(idle_load_pcts);
68 | return pwr;
69 | }
70 |
71 | // 如果负载没有被移动到大核,则认为大核没有闲置耗电,减少待机时大核上线概率
72 | inline int Hmp::CalcPowerForIdle(const int *loads) const {
73 | const int idle_load_pcts[] = {100, 0, 0, 0};
74 | int pwr = 0;
75 | if (active_ == little_) {
76 | pwr += little_->CalcPower(idle_load_pcts);
77 | } else {
78 | pwr += little_->CalcPower(idle_load_pcts);
79 | pwr += big_->CalcPower(idle_load_pcts);
80 | }
81 | return pwr;
82 | }
83 |
84 | #endif
85 |
--------------------------------------------------------------------------------
/source/sim/hmp_pelt.cpp:
--------------------------------------------------------------------------------
1 | #include "hmp_pelt.h"
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | /* Precomputed fixed inverse multiplies for multiplication by y^n */
11 | // runnable_avg_yN_inv[i] = ((1UL << 32) - 1) * pow(0.97857206, i),i>=0 && i<32
12 | static const uint32_t runnable_avg_yN_inv[] = {
13 | 0xffffffff, 0xfa83b2da, 0xf5257d14, 0xefe4b99a, 0xeac0c6e6, 0xe5b906e6, 0xe0ccdeeb, 0xdbfbb796,
14 | 0xd744fcc9, 0xd2a81d91, 0xce248c14, 0xc9b9bd85, 0xc5672a10, 0xc12c4cc9, 0xbd08a39e, 0xb8fbaf46,
15 | 0xb504f333, 0xb123f581, 0xad583ee9, 0xa9a15ab4, 0xa5fed6a9, 0xa2704302, 0x9ef5325f, 0x9b8d39b9,
16 | 0x9837f050, 0x94f4efa8, 0x91c3d373, 0x8ea4398a, 0x8b95c1e3, 0x88980e80, 0x85aac367, 0x82cd8698,
17 | };
18 | #define LOAD_AVG_PERIOD 32
19 | #define LOAD_AVG_MAX 47742 /* maximum possible load avg */
20 | #define LOAD_AVG_MAX_N 345 /* number of full periods to produce LOAD_AVG_MAX */
21 |
22 | // a * mul >> shift
23 | static inline uint64_t mul_u64_u32_shr(uint64_t a, uint32_t mul, unsigned int shift) {
24 | uint32_t ah, al;
25 | uint64_t ret;
26 |
27 | al = a;
28 | ah = a >> 32;
29 |
30 | ret = ((uint64_t)al * mul) >> shift;
31 | if (ah)
32 | ret += ((uint64_t)ah * mul) << (32 - shift);
33 |
34 | return ret;
35 | }
36 |
37 | /*
38 | * Approximate:
39 | * val * y^n, where y^32 ~= 0.5 (~1 scheduling period)
40 | */
41 | static inline uint64_t decay_load(uint64_t val, uint64_t n) {
42 | // unsigned int local_n;
43 |
44 | // if (!n)
45 | // return val;
46 | // else if (unlikely(n > LOAD_AVG_PERIOD * 63))
47 | // return 0;
48 |
49 | // /* after bounds checking we can collapse to 32-bit */
50 | // local_n = n;
51 |
52 | // /*
53 | // * As y^PERIOD = 1/2, we can combine
54 | // * y^n = 1/2^(n/PERIOD) * y^(n%PERIOD)
55 | // * With a look-up table which covers y^n (n= LOAD_AVG_PERIOD)) {
60 | // val >>= local_n / LOAD_AVG_PERIOD;
61 | // local_n %= LOAD_AVG_PERIOD;
62 | // }
63 | // /*正好符合:load = (load >> (n/period)) * y^(n%period)计算方式*/
64 | // val = mul_u64_u32_shr(val, runnable_avg_yN_inv[local_n], 32);
65 | return val;
66 | }
67 |
68 | uint32_t CalcDecayRatio(int ms, int n) {
69 | // 在LOAD_AVG_PERIOD毫秒时的负载,在当前计算衰减一半
70 | // y为1毫秒前负载的衰减,n为毫秒数,y ^ n = 0.5
71 | double y = pow(0.5, 1.0 / n);
72 | return (UINT32_MAX * pow(y, ms));
73 | }
74 |
75 | // 根据decay_ratio(0.97 * UINTMAX)计算LoadAvgMax
76 | // CalcDecayRatio(1, 32) -> 47742,迭代348次
77 | // CalcDecayRatio(10, 32) -> 5253,迭代36次
78 | uint32_t CalcLoadAvgMax(uint32_t decay_ratio) {
79 | uint32_t max = 0;
80 | uint32_t last = UINT32_MAX;
81 | while (max != last) {
82 | last = max;
83 | max = 1024 + mul_u64_u32_shr(max, decay_ratio, 32);
84 | }
85 | return max;
86 | }
87 |
88 | PeltHmp::Tunables::Tunables() {
89 | down_threshold = 214;
90 | up_threshold = 524;
91 | load_avg_period_ms = 128;
92 | boost = 0;
93 | timer_rate = 2;
94 | }
95 |
96 | #define TICK_MS 10
97 | PeltHmp::PeltHmp(Cfg cfg)
98 | : Hmp(cfg), demand_(0), entry_cnt_(0), max_load_sum_(0), decay_ratio_(0), load_avg_max_(0), governor_cnt_(0) {
99 | SetTunables(cfg.tunables);
100 | InitDecay(TICK_MS, tunables_.load_avg_period_ms);
101 | }
102 |
103 | void PeltHmp::SetTunables(const Tunables &t) {
104 | tunables_ = t;
105 | up_demand_thd_ = tunables_.up_threshold;
106 | down_demand_thd_ = tunables_.down_threshold;
107 | }
108 |
109 | void PeltHmp::InitDecay(int ms, int n) {
110 | decay_ratio_ = CalcDecayRatio(TICK_MS, tunables_.load_avg_period_ms);
111 | load_avg_max_ = CalcLoadAvgMax(decay_ratio_);
112 | }
113 |
114 | #define THRESHOLD_SCALE 1024
115 | // 用于大小核迁移的使用率计算,以最大可达到的使用率为1024
116 | // 注意这个使用率不考虑当前集群的频率和IPC,仅与CPU忙时间有关
117 | // 同样的负载,在容量较高的核心上使用率会低一些,在容量较低的核心上使用率会高一些
118 | uint64_t PeltHmp::UpdateBusyTime(int max_load) {
119 | // 转换到负载百分比,映射到0~1024
120 | uint64_t now = LoadToBusyPct(active_, max_load) * THRESHOLD_SCALE / 100;
121 | // 衰减之前的负载,加上新的,如果是持续稳定负载类似于等比数列求和
122 | demand_ = now + mul_u64_u32_shr(demand_, decay_ratio_, 32);
123 | // 以最大可达到的使用率为1024
124 | return demand_ * THRESHOLD_SCALE / load_avg_max_;
125 | }
126 |
127 | // demand : freq * busy_pct * efficiency
128 | // load: freq * busy_pct * efficiency
129 | // load 最大值 2500 * 2048 * 100,sum最大值 3000 * 2048 * 400,可能大于UINT32_MAX
130 | int PeltHmp::SchedulerTick(int max_load, const int *loads, int n_load, int now) {
131 | // 仅用于负载迁移判断,调频器仍然使用定期负载采样
132 | // 注意这个使用率不考虑当前集群的频率和IPC,仅与CPU忙时间有关
133 | uint64_t busy = UpdateBusyTime(max_load);
134 | if (busy > up_demand_thd_) {
135 | active_ = big_;
136 | idle_ = little_;
137 | } else if (busy < down_demand_thd_) {
138 | active_ = little_;
139 | idle_ = big_;
140 | } else {
141 | ;
142 | }
143 |
144 | ++entry_cnt_;
145 | max_load_sum_ += max_load;
146 |
147 | if (entry_cnt_ == tunables_.timer_rate) {
148 | int max_load_avg = max_load_sum_ / tunables_.timer_rate;
149 | entry_cnt_ = 0;
150 | max_load_sum_ = 0;
151 |
152 | // 调频器仍然使用定期负载采样
153 | idle_->SetBusyPct(0);
154 | active_->SetBusyPct(LoadToBusyPct(active_, max_load_avg));
155 |
156 | little_->SetCurfreq(governor_little_->InteractiveTimer(little_->GetBusyPct(), governor_cnt_));
157 | if (cluster_num_ > 1)
158 | big_->SetCurfreq(governor_big_->InteractiveTimer(big_->GetBusyPct(), governor_cnt_));
159 |
160 | ++governor_cnt_;
161 | }
162 |
163 | return active_->CalcCapacity();
164 | }
165 |
--------------------------------------------------------------------------------
/source/sim/hmp_pelt.h:
--------------------------------------------------------------------------------
1 | #ifndef __HMP_PELT_H
2 | #define __HMP_PELT_H
3 |
4 | #include "hmp.h"
5 |
6 | class PeltHmp : public Hmp {
7 | public:
8 | struct Tunables : public HmpTunables {
9 | int load_avg_period_ms;
10 | int down_threshold;
11 | int up_threshold;
12 | int boost;
13 | int timer_rate;
14 | Tunables();
15 | };
16 |
17 | struct Cfg : public HmpCfg {
18 | Tunables tunables;
19 | };
20 |
21 | PeltHmp(){};
22 | PeltHmp(Cfg cfg);
23 | int SchedulerTick(int max_load, const int *loads, int n_load, int now);
24 |
25 | Tunables GetTunables(void) { return tunables_; }
26 | void SetTunables(const Tunables &t);
27 |
28 | private:
29 | uint64_t UpdateBusyTime(int max_load);
30 | void InitDecay(int ms, int n);
31 |
32 | Tunables tunables_;
33 | uint64_t demand_;
34 | int entry_cnt_;
35 | uint64_t max_load_sum_;
36 | uint32_t decay_ratio_;
37 | uint32_t load_avg_max_;
38 | int governor_cnt_;
39 | };
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/source/sim/hmp_walt.cpp:
--------------------------------------------------------------------------------
1 | #include "hmp_walt.h"
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | WaltHmp::Tunables::Tunables() {
10 | sched_downmigrate = 85;
11 | sched_upmigrate = 95;
12 | sched_ravg_hist_size = 5;
13 | sched_window_stats_policy = WaltHmp::WINDOW_STATS_MAX_RECENT_AVG;
14 | sched_boost = 0;
15 | timer_rate = 2;
16 | }
17 |
18 | WaltHmp::WaltHmp(Cfg cfg)
19 | : Hmp(cfg), tunables_(cfg.tunables), demand_(0), entry_cnt_(0), max_load_sum_(0), governor_cnt_(0) {
20 | SetTunables(cfg.tunables);
21 | memset(sum_history_, 0, sizeof(sum_history_));
22 | memset(loads_sum_, 0, sizeof(loads_sum_));
23 | }
24 |
25 | void WaltHmp::SetTunables(const Tunables &t) {
26 | tunables_ = t;
27 | // Hence this threshold is auto-adjusted by a factor
28 | // equal to max_possible_frequency/current_frequency of a lower capacity CPU
29 | up_demand_thd_ = little_->model_.max_freq * little_->model_.efficiency * tunables_.sched_upmigrate;
30 | down_demand_thd_ = little_->model_.max_freq * little_->model_.efficiency * tunables_.sched_downmigrate;
31 | }
32 |
33 | // 更新负载滑动窗口,返回预计的负载需求,@in_demand为freq*busy_pct*efficiency
34 | void WaltHmp::update_history(int in_demand) {
35 | int * hist = sum_history_;
36 | uint64_t sum = 0;
37 | constexpr int samples = 1;
38 | const int runtime = in_demand;
39 | int max = 0;
40 | int ridx, widx;
41 | int avg, demand;
42 |
43 | /* Push new 'runtime' value onto stack */
44 | widx = tunables_.sched_ravg_hist_size - 1;
45 | ridx = widx - samples;
46 | for (; ridx >= 0; --widx, --ridx) {
47 | hist[widx] = hist[ridx];
48 | sum += hist[widx];
49 | if (hist[widx] > max)
50 | max = hist[widx];
51 | }
52 |
53 | for (widx = 0; widx < samples && widx < tunables_.sched_ravg_hist_size; widx++) {
54 | hist[widx] = runtime;
55 | sum += hist[widx];
56 | if (hist[widx] > max)
57 | max = hist[widx];
58 | }
59 |
60 | if (tunables_.sched_window_stats_policy == WINDOW_STATS_RECENT) {
61 | demand = runtime;
62 | } else if (tunables_.sched_window_stats_policy == WINDOW_STATS_MAX) {
63 | demand = max;
64 | } else {
65 | avg = sum / tunables_.sched_ravg_hist_size;
66 | if (tunables_.sched_window_stats_policy == WINDOW_STATS_AVG)
67 | demand = avg;
68 | else
69 | demand = std::max(avg, runtime);
70 | }
71 |
72 | demand_ = demand;
73 | return;
74 | }
75 |
76 | // demand : freq * busy_pct * efficiency,walt输出
77 | // load: freq * busy_pct * efficiency
78 | // load 最大值 2500 * 2048 * 100,sum最大值 3000 * 2048 * 400,可能大于UINT32_MAX
79 | int WaltHmp::SchedulerTick(int max_load, const int *loads, int n_load, int now) {
80 | ++entry_cnt_;
81 | max_load_sum_ += max_load;
82 | for (int i = 0; i < n_load; ++i) {
83 | loads_sum_[i] += loads[i];
84 | }
85 |
86 | if (entry_cnt_ == tunables_.timer_rate) {
87 | int max_load_avg = max_load_sum_ / tunables_.timer_rate;
88 |
89 | entry_cnt_ = 0;
90 | max_load_sum_ = 0;
91 | memset(loads_sum_, 0, sizeof(loads_sum_));
92 |
93 | update_history(max_load_avg);
94 |
95 | if (demand_ > up_demand_thd_) {
96 | active_ = big_;
97 | idle_ = little_;
98 | } else if (demand_ < down_demand_thd_) {
99 | active_ = little_;
100 | idle_ = big_;
101 | } else {
102 | ;
103 | }
104 |
105 | if (tunables_.sched_boost) {
106 | active_ = big_;
107 | idle_ = little_;
108 | }
109 |
110 | // 调频器使用定期负载采样
111 | idle_->SetBusyPct(0);
112 | active_->SetBusyPct(LoadToBusyPct(active_, max_load_avg));
113 |
114 | little_->SetCurfreq(governor_little_->InteractiveTimer(little_->GetBusyPct(), governor_cnt_));
115 | if (cluster_num_ > 1)
116 | big_->SetCurfreq(governor_big_->InteractiveTimer(big_->GetBusyPct(), governor_cnt_));
117 |
118 | ++governor_cnt_;
119 | }
120 |
121 | return active_->CalcCapacity();
122 | }
123 |
--------------------------------------------------------------------------------
/source/sim/hmp_walt.h:
--------------------------------------------------------------------------------
1 | #ifndef __HMP_WALT_H
2 | #define __HMP_WALT_H
3 |
4 | #include "hmp.h"
5 |
6 | class WaltHmp : public Hmp {
7 | public:
8 | enum { WINDOW_STATS_RECENT = 0, WINDOW_STATS_MAX, WINDOW_STATS_MAX_RECENT_AVG, WINDOW_STATS_AVG };
9 |
10 | struct Tunables : public HmpTunables {
11 | int timer_rate;
12 | int sched_upmigrate;
13 | int sched_downmigrate;
14 | int sched_ravg_hist_size;
15 | int sched_window_stats_policy;
16 | int sched_boost;
17 | Tunables();
18 | };
19 |
20 | struct Cfg : public HmpCfg {
21 | Tunables tunables;
22 | };
23 |
24 | WaltHmp(){};
25 | WaltHmp(Cfg cfg);
26 | int SchedulerTick(int max_load, const int *loads, int n_load, int now);
27 |
28 | Tunables GetTunables(void) { return tunables_; }
29 | void SetTunables(const Tunables &t);
30 |
31 | private:
32 | #define RavgHistSizeMax 5
33 |
34 | void update_history(int in_demand);
35 |
36 | Tunables tunables_;
37 | uint64_t demand_;
38 | int sum_history_[RavgHistSizeMax];
39 | int entry_cnt_;
40 | uint64_t max_load_sum_;
41 | uint64_t loads_sum_[NLoadsMax];
42 | int governor_cnt_;
43 | };
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/source/sim/input_boost.cpp:
--------------------------------------------------------------------------------
1 | #include "input_boost.h"
2 |
3 | #include "hmp_pelt.h"
4 | #include "hmp_walt.h"
5 |
6 | template
7 | InputBoost::Tunables::Tunables(const Soc *soc) {
8 | int idx = 0;
9 | for (const auto &cluster : soc->clusters_) {
10 | boost_freq[idx++] = cluster.freq_floor_to_opp(cluster.model_.max_freq * 0.6);
11 | }
12 | // 默认不拉大核的最低频率
13 | if (soc->clusters_.size() > 1)
14 | boost_freq[1] = soc->clusters_[1].model_.min_freq;
15 | duration_quantum = 100;
16 | }
17 |
18 | template
19 | void InputBoost::DoBoost() {
20 | auto &cls = this->env_.soc->clusters_;
21 | int nr = cls.size();
22 | for (int i = 0; i < nr; ++i)
23 | cls[i].SetMinfreq(tunables_.boost_freq[i]);
24 | }
25 |
26 | template
27 | void InputBoost::DoResume() {
28 | auto &cls = this->env_.soc->clusters_;
29 | int nr = cls.size();
30 | for (int i = 0; i < nr; ++i)
31 | cls[i].SetMinfreq(cls[i].model_.min_freq);
32 | }
33 |
34 | template
35 | void InputBoost::Tick(bool has_input, bool has_render, int cur_quantum) {
36 | if (tunables_.duration_quantum && has_input) {
37 | this->input_happened_quantum_ = cur_quantum;
38 | DoBoost();
39 | this->is_in_boost_ = true;
40 | return;
41 | }
42 | if (this->is_in_boost_ && cur_quantum - this->input_happened_quantum_ > tunables_.duration_quantum) {
43 | DoResume();
44 | this->is_in_boost_ = false;
45 | }
46 | };
47 |
48 | template <>
49 | UperfBoost::Tunables::Tunables(const Soc *soc) {
50 | int cluster_num = soc->clusters_.size();
51 | auto sched_tunables = WaltHmp::Tunables();
52 | for (int i = 0; i < cluster_num; ++i) {
53 | const auto &cl = soc->clusters_[i];
54 | min_freq[i] = cl.model_.min_freq;
55 | max_freq[i] = cl.model_.max_freq;
56 | }
57 | sched_up = sched_tunables.sched_upmigrate;
58 | sched_down = sched_tunables.sched_downmigrate;
59 | little = Interactive::Tunables(soc->clusters_[soc->GetLittleClusterIdx()]);
60 | big = Interactive::Tunables(soc->clusters_[soc->GetBigClusterIdx()]);
61 | enabled = true;
62 | }
63 |
64 | template <>
65 | UperfBoost::Tunables::Tunables(const Soc *soc) {
66 | int cluster_num = soc->clusters_.size();
67 | auto sched_tunables = PeltHmp::Tunables();
68 | for (int i = 0; i < cluster_num; ++i) {
69 | const auto &cl = soc->clusters_[i];
70 | min_freq[i] = cl.model_.min_freq;
71 | max_freq[i] = cl.model_.max_freq;
72 | }
73 | sched_up = sched_tunables.up_threshold;
74 | sched_down = sched_tunables.down_threshold;
75 | little = Interactive::Tunables(soc->clusters_[soc->GetLittleClusterIdx()]);
76 | big = Interactive::Tunables(soc->clusters_[soc->GetBigClusterIdx()]);
77 | enabled = true;
78 | }
79 |
80 | template
81 | void UperfBoost::DoBoost() {
82 | if (is_original_inited_ == false) {
83 | is_original_inited_ = true;
84 | Backup();
85 | }
86 | Apply(tunables_);
87 | }
88 |
89 | template
90 | void UperfBoost::DoResume() {
91 | Apply(original_);
92 | }
93 |
94 | template
95 | void UperfBoost::Tick(bool has_input, bool has_render, int cur_quantum) {
96 | if (tunables_.enabled == false)
97 | return;
98 |
99 | if (has_input) {
100 | this->input_happened_quantum_ = cur_quantum;
101 | }
102 | if (has_render) {
103 | this->render_stop_quantum_ = cur_quantum;
104 | }
105 |
106 | if (this->is_in_boost_ == false) {
107 | if (has_input) {
108 | this->render_stop_quantum_ = cur_quantum;
109 | DoBoost();
110 | this->is_in_boost_ = true;
111 | }
112 | } else {
113 | // uperf在渲染结束后至多300ms,或者触摸停止后3000ms,停止hint
114 | bool is_touch_timeout = cur_quantum - this->input_happened_quantum_ > 300;
115 | bool is_render_stop = cur_quantum - this->render_stop_quantum_ > 30;
116 | if (is_touch_timeout || is_render_stop) {
117 | DoResume();
118 | this->is_in_boost_ = false;
119 | }
120 | }
121 | };
122 |
123 | template <>
124 | void UperfBoost::Apply(const typename UperfBoost::Tunables &t) {
125 | auto soc = this->env_.soc;
126 | // auto little = this->env_.little;
127 | // auto big = this->env_.big;
128 | auto sched = this->env_.sched;
129 |
130 | int cluster_num = soc->clusters_.size();
131 | auto sched_tunables = sched->GetTunables();
132 | for (int i = 0; i < cluster_num; ++i) {
133 | soc->clusters_[i].SetMinfreq(t.min_freq[i]);
134 | soc->clusters_[i].SetMaxfreq(t.max_freq[i]);
135 | }
136 | sched_tunables.sched_upmigrate = t.sched_up;
137 | sched_tunables.sched_downmigrate = t.sched_down;
138 | sched->SetTunables(sched_tunables);
139 | // little->SetTunables(t.little);
140 | // big->SetTunables(t.big);
141 | }
142 |
143 | template <>
144 | void UperfBoost::Apply(const typename UperfBoost::Tunables &t) {
145 | auto soc = this->env_.soc;
146 | // auto little = this->env_.little;
147 | // auto big = this->env_.big;
148 | auto sched = this->env_.sched;
149 |
150 | int cluster_num = soc->clusters_.size();
151 | auto sched_tunables = sched->GetTunables();
152 | for (int i = 0; i < cluster_num; ++i) {
153 | soc->clusters_[i].SetMinfreq(t.min_freq[i]);
154 | soc->clusters_[i].SetMaxfreq(t.max_freq[i]);
155 | }
156 | sched_tunables.up_threshold = t.sched_up;
157 | sched_tunables.down_threshold = t.sched_down;
158 | sched->SetTunables(sched_tunables);
159 | // little->SetTunables(t.little);
160 | // big->SetTunables(t.big);
161 | }
162 |
163 | template <>
164 | void UperfBoost::Backup() {
165 | const auto soc = this->env_.soc;
166 | const auto little = this->env_.little;
167 | const auto big = this->env_.big;
168 | const auto sched = this->env_.sched;
169 |
170 | int cluster_num = soc->clusters_.size();
171 | auto sched_tunables = sched->GetTunables();
172 | for (int i = 0; i < cluster_num; ++i) {
173 | original_.min_freq[i] = soc->clusters_[i].model_.min_freq;
174 | original_.max_freq[i] = soc->clusters_[i].model_.max_freq;
175 | }
176 | original_.sched_up = sched_tunables.sched_upmigrate;
177 | original_.sched_down = sched_tunables.sched_downmigrate;
178 | original_.little = little->GetTunables();
179 | original_.big = big->GetTunables();
180 | }
181 |
182 | template <>
183 | void UperfBoost::Backup() {
184 | const auto soc = this->env_.soc;
185 | const auto little = this->env_.little;
186 | const auto big = this->env_.big;
187 | const auto sched = this->env_.sched;
188 |
189 | int cluster_num = soc->clusters_.size();
190 | auto sched_tunables = sched->GetTunables();
191 | for (int i = 0; i < cluster_num; ++i) {
192 | original_.min_freq[i] = soc->clusters_[i].model_.min_freq;
193 | original_.max_freq[i] = soc->clusters_[i].model_.max_freq;
194 | }
195 | original_.sched_up = sched_tunables.up_threshold;
196 | original_.sched_down = sched_tunables.down_threshold;
197 | original_.little = little->GetTunables();
198 | original_.big = big->GetTunables();
199 | }
200 |
201 | template class InputBoost;
202 | template class InputBoost;
203 | template class UperfBoost;
204 | template class UperfBoost;
205 |
--------------------------------------------------------------------------------
/source/sim/input_boost.h:
--------------------------------------------------------------------------------
1 | #ifndef __INPUT_BOOST_H
2 | #define __INPUT_BOOST_H
3 |
4 | #include "cpumodel.h"
5 |
6 | template
7 | class Boost {
8 | public:
9 | struct SysEnv {
10 | Soc * soc;
11 | GovernorT *little;
12 | GovernorT *big;
13 | SchedT * sched;
14 | };
15 |
16 | Boost() : env_(), is_in_boost_(false) {}
17 | Boost(const SysEnv &env) : env_(env), is_in_boost_(false) {}
18 | void Tick(bool has_input, bool has_render, int cur_quantum) {}
19 |
20 | protected:
21 | void DoBoost(void) {}
22 | void DoResume(void) {}
23 |
24 | SysEnv env_;
25 | bool is_in_boost_;
26 | };
27 |
28 | template
29 | class InputBoost : public Boost {
30 | public:
31 | struct Tunables {
32 | int boost_freq[2];
33 | int duration_quantum;
34 | Tunables() : boost_freq{0, 0}, duration_quantum(0) {}
35 | Tunables(const Soc *soc);
36 | };
37 |
38 | InputBoost() : Boost(), tunables_(), input_happened_quantum_(0) {}
39 | InputBoost(const Tunables &tunables, const typename Boost::SysEnv &env)
40 | : Boost(env), tunables_(tunables), input_happened_quantum_(0) {}
41 | void Tick(bool has_input, bool has_render, int cur_quantum);
42 |
43 | private:
44 | void DoBoost(void);
45 | void DoResume(void);
46 |
47 | Tunables tunables_;
48 | int input_happened_quantum_;
49 | };
50 |
51 | template
52 | class UperfBoost : public Boost {
53 | public:
54 | struct Tunables {
55 | int min_freq[2];
56 | int max_freq[2];
57 | int sched_up;
58 | int sched_down;
59 | typename GovernorT::Tunables little;
60 | typename GovernorT::Tunables big;
61 | bool enabled;
62 | Tunables() : min_freq{0, 0}, max_freq{0, 0}, sched_up(0), sched_down(0), enabled(false) {}
63 | Tunables(const Soc *soc);
64 | };
65 |
66 | UperfBoost()
67 | : Boost(),
68 | tunables_(),
69 | original_(),
70 | is_original_inited_(false),
71 | render_stop_quantum_(0),
72 | input_happened_quantum_(0) {}
73 | UperfBoost(const Tunables &tunables, const typename Boost::SysEnv &env)
74 | : Boost(env),
75 | tunables_(tunables),
76 | original_(),
77 | is_original_inited_(false),
78 | render_stop_quantum_(0),
79 | input_happened_quantum_(0) {}
80 | void Tick(bool has_input, bool has_render, int cur_quantum);
81 |
82 | private:
83 | void DoBoost(void);
84 | void DoResume(void);
85 | void Apply(const Tunables &t);
86 | void Backup(void);
87 |
88 | Tunables tunables_;
89 | Tunables original_;
90 |
91 | bool is_original_inited_;
92 | int render_stop_quantum_;
93 | int input_happened_quantum_;
94 | };
95 |
96 | #endif
--------------------------------------------------------------------------------
/source/sim/interactive.cpp:
--------------------------------------------------------------------------------
1 | #include "interactive.h"
2 |
3 | #include
4 | extern "C" {
5 | #include
6 | #include
7 | }
8 |
9 | Interactive::Tunables::_InteractiveTunables(const Cluster &cm) {
10 | hispeed_freq = cm.freq_floor_to_opp(cm.model_.max_freq * 0.6);
11 | go_hispeed_load = 90;
12 | min_sample_time = 1;
13 | max_freq_hysteresis = 2;
14 |
15 | int n_opp = cm.model_.opp_model.size();
16 | int n_above = std::min(ABOVE_DELAY_MAX_LEN, n_opp);
17 | int n_targetloads = std::min(TARGET_LOAD_MAX_LEN, n_opp);
18 |
19 | for (int i = 0; i < n_above; ++i) {
20 | above_hispeed_delay[i] = 1;
21 | }
22 | for (int i = 0; i < n_targetloads; ++i) {
23 | target_loads[i] = 90;
24 | }
25 | }
26 |
27 | int Interactive::choose_freq(int freq, int load) const {
28 | const int loadadjfreq = freq * load;
29 | int prevfreq, freqmin, freqmax, tl;
30 |
31 | freqmin = 0;
32 | freqmax = INT_MAX;
33 |
34 | do {
35 | prevfreq = freq;
36 | tl = freq_to_targetload(freq);
37 | freq = cluster_->freq_floor_to_opp(loadadjfreq / tl);
38 |
39 | if (freq > prevfreq) {
40 | /* The previous frequency is too low. */
41 | freqmin = prevfreq;
42 | if (freq >= freqmax) {
43 | freq = cluster_->freq_ceiling_to_opp(freqmax - 1);
44 | if (freq == freqmin) {
45 | freq = freqmax;
46 | break;
47 | }
48 | }
49 | } else if (freq < prevfreq) {
50 | /* The previous frequency is high enough. */
51 | freqmax = prevfreq;
52 | if (freq <= freqmin) {
53 | freq = cluster_->freq_floor_to_opp(freqmin + 1);
54 | if (freq == freqmax)
55 | break;
56 | }
57 | }
58 | } while (freq != prevfreq);
59 |
60 | return freq;
61 | }
62 |
63 | int Interactive::InteractiveTimer(int load, int now) {
64 | bool skip_hispeed_logic = false;
65 | bool skip_min_sample_time = false;
66 | bool jump_to_max_no_ts = false;
67 | bool jump_to_max = false;
68 | constexpr bool boosted = 0;
69 | // bool boosted = now < boostpulse_endtime; // touch->store_boostpulse->boostpulse_endtime
70 | // 通路不再使用,改用input_boost
71 | int new_freq = choose_freq(target_freq, load);
72 | // printf("choosefreq:%d\n", new_freq);
73 |
74 | if (now - max_freq_hyst_start_time < tunables_.max_freq_hysteresis && load >= tunables_.go_hispeed_load) {
75 | skip_hispeed_logic = true;
76 | skip_min_sample_time = true;
77 | if (!jump_to_max)
78 | jump_to_max_no_ts = true;
79 | }
80 |
81 | if (jump_to_max_no_ts || jump_to_max) {
82 | new_freq = cluster_->GetMaxfreq();
83 | } else if (!skip_hispeed_logic) {
84 | if (load >= tunables_.go_hispeed_load || boosted) {
85 | if (target_freq < tunables_.hispeed_freq)
86 | new_freq = tunables_.hispeed_freq;
87 | else
88 | new_freq = std::max(new_freq, tunables_.hispeed_freq);
89 | }
90 | }
91 |
92 | if (now - max_freq_hyst_start_time < tunables_.max_freq_hysteresis) {
93 | new_freq = std::max(tunables_.hispeed_freq, new_freq);
94 | }
95 | if (!skip_hispeed_logic && target_freq >= tunables_.hispeed_freq && new_freq > target_freq &&
96 | now - hispeed_validate_time < freq_to_above_hispeed_delay(target_freq)) {
97 | return target_freq;
98 | }
99 |
100 | hispeed_validate_time = now;
101 |
102 | new_freq = cluster_->freq_floor_to_opp(new_freq);
103 |
104 | /*
105 | * Do not scale below floor_freq unless we have been at or above the
106 | * floor frequency for the minimum sample time since last validated.
107 | */
108 | if (!skip_min_sample_time && new_freq < floor_freq) {
109 | if (now - floor_validate_time < tunables_.min_sample_time) {
110 | return target_freq;
111 | }
112 | }
113 |
114 | /*
115 | * Update the timestamp for checking whether speed has been held at
116 | * or above the selected frequency for a minimum of min_sample_time,
117 | * if not boosted to hispeed_freq. If boosted to hispeed_freq then we
118 | * allow the speed to drop as soon as the boostpulse duration expires
119 | * (or the indefinite boost is turned off). If policy->max is restored
120 | * for max_freq_hysteresis, don't extend the timestamp. Otherwise, it
121 | * could incorrectly extended the duration of max_freq_hysteresis by
122 | * min_sample_time.
123 | */
124 | if ((!boosted || new_freq > tunables_.hispeed_freq) && !jump_to_max_no_ts) {
125 | floor_freq = new_freq;
126 | floor_validate_time = now;
127 | }
128 |
129 | if (new_freq >= cluster_->GetMaxfreq() && !jump_to_max_no_ts) {
130 | max_freq_hyst_start_time = now;
131 | }
132 | target_freq = new_freq;
133 |
134 | return target_freq;
135 | }
136 |
137 | int Interactive::GetAboveHispeedDelayGearNum(void) const {
138 | auto get_freq = [=](int idx) { return cluster_->model_.opp_model[idx].freq; };
139 |
140 | const auto &t = tunables_;
141 | const int n_opp = cluster_->model_.opp_model.size();
142 | const int n_above = std::min(ABOVE_DELAY_MAX_LEN, n_opp);
143 |
144 | int anchor_val = -1;
145 | int n_gears = 0;
146 |
147 | for (int i = 0; i < n_above; ++i) {
148 | if (get_freq(i) < t.hispeed_freq) {
149 | continue;
150 | }
151 | if (anchor_val != t.above_hispeed_delay[i]) {
152 | anchor_val = t.above_hispeed_delay[i];
153 | n_gears++;
154 | }
155 | }
156 |
157 | return n_gears;
158 | }
159 |
160 | int Interactive::GetTargetLoadGearNum(void) const {
161 | const auto &t = tunables_;
162 | const int n_opp = cluster_->model_.opp_model.size();
163 | const int n_targetloads = std::min(TARGET_LOAD_MAX_LEN, n_opp);
164 |
165 | int anchor_val = -1;
166 | int n_gears = 0;
167 |
168 | for (int i = 0; i < n_targetloads; ++i) {
169 | if (anchor_val != t.target_loads[i]) {
170 | anchor_val = t.target_loads[i];
171 | n_gears++;
172 | }
173 | }
174 |
175 | return n_gears;
176 | }
177 |
--------------------------------------------------------------------------------
/source/sim/interactive.h:
--------------------------------------------------------------------------------
1 | #ifndef __INTERACTIVE_H
2 | #define __INTERACTIVE_H
3 |
4 | #include
5 |
6 | #include "cpumodel.h"
7 |
8 | const int kInteractiveParamFixedLen = 4;
9 | #define TARGET_LOAD_MAX_LEN 24
10 | #define ABOVE_DELAY_MAX_LEN 32
11 |
12 | class Interactive {
13 | public:
14 | typedef struct _InteractiveTunables {
15 | int hispeed_freq;
16 | uint16_t go_hispeed_load;
17 | uint8_t min_sample_time;
18 | uint8_t max_freq_hysteresis;
19 | uint8_t above_hispeed_delay[ABOVE_DELAY_MAX_LEN];
20 | uint8_t target_loads[TARGET_LOAD_MAX_LEN];
21 | _InteractiveTunables(const Cluster &cm);
22 | _InteractiveTunables() {}
23 | } Tunables;
24 |
25 | Interactive() = delete;
26 | Interactive(Tunables tunables, Cluster *cm)
27 | : tunables_(tunables),
28 | cluster_(cm),
29 | target_freq(cm->model_.max_freq),
30 | floor_freq(cm->model_.max_freq),
31 | max_freq_hyst_start_time(0),
32 | hispeed_validate_time(0),
33 | floor_validate_time(0) {}
34 |
35 | int InteractiveTimer(int load, int now);
36 | int GetAboveHispeedDelayGearNum(void) const;
37 | int GetTargetLoadGearNum(void) const;
38 |
39 | Tunables GetTunables(void) { return tunables_; }
40 | void SetTunables(const Tunables &t) { tunables_ = t; }
41 |
42 | private:
43 | int freq_to_targetload(int freq) const;
44 | int freq_to_above_hispeed_delay(int freq) const;
45 | int choose_freq(int freq, int load) const;
46 |
47 | Tunables tunables_;
48 | const Cluster *cluster_;
49 |
50 | int target_freq;
51 | int floor_freq;
52 | int max_freq_hyst_start_time;
53 | int hispeed_validate_time;
54 | int floor_validate_time;
55 | };
56 |
57 | inline int Interactive::freq_to_targetload(int freq) const {
58 | return tunables_.target_loads[std::min(TARGET_LOAD_MAX_LEN - 1, cluster_->FindFreqIdx(freq, -1, -1))];
59 | }
60 |
61 | inline int Interactive::freq_to_above_hispeed_delay(int freq) const {
62 | return tunables_.above_hispeed_delay[std::min(ABOVE_DELAY_MAX_LEN - 1, cluster_->FindFreqIdx(freq, -1, -1))];
63 | }
64 |
65 | #endif
66 |
--------------------------------------------------------------------------------
/source/sim/rank.cpp:
--------------------------------------------------------------------------------
1 | #include "rank.h"
2 |
3 | #include
4 |
5 | Rank::Score Rank::Eval(const Workload &workload, const Workload &idleload, const SimResultPack &rp, Soc soc,
6 | bool is_init) {
7 | if (is_init) {
8 | default_score_.ref_power_comsumed = InitRefBattPartition(rp.onscreen.power);
9 | }
10 |
11 | double perf = EvalPerformance(workload, soc, rp.onscreen.capacity);
12 | double work_lasting = EvalBatterylife(rp.onscreen.power);
13 | double idle_lasting = EvalIdleLasting(rp.offscreen_pwr);
14 |
15 | if (is_init) {
16 | return {perf, work_lasting, idle_lasting, default_score_.ref_power_comsumed};
17 | } else {
18 | return {perf, work_lasting, idle_lasting, {0}};
19 | }
20 | }
21 |
22 | double Rank::EvalPerformance(const Workload &workload, const Soc &soc, const SimSeq &capacity_log) {
23 | const int enough_capacity = soc.GetEnoughCapacity();
24 | const int max_capacity = soc.GetMaxCapacity();
25 | const int margin_capacity = max_capacity - enough_capacity;
26 |
27 | auto calc_lag = [=](int required, int provided) {
28 | if (provided >= max_capacity) {
29 | return 0.0;
30 | }
31 | if (provided < required) {
32 | if (provided >= enough_capacity) {
33 | return misc_.enough_penalty * (max_capacity - provided) / margin_capacity;
34 | } else {
35 | return 1.0;
36 | }
37 | } else {
38 | return 0.0;
39 | }
40 | return 0.0;
41 | };
42 |
43 | LagSeq common_lag_seq;
44 | common_lag_seq.reserve(capacity_log.size());
45 |
46 | auto iter_log = capacity_log.begin();
47 | for (const auto &loadslice : workload.windowed_load_) {
48 | common_lag_seq.push_back(calc_lag(loadslice.max_load, *iter_log++));
49 | }
50 |
51 | LagSeq render_lag_seq;
52 | render_lag_seq.reserve(workload.render_load_.size());
53 |
54 | for (const auto &r : workload.render_load_) {
55 | uint64_t aggreated_capacity = 0;
56 | aggreated_capacity += capacity_log[r.window_idxs[0]] * r.window_quantums[0];
57 | aggreated_capacity += capacity_log[r.window_idxs[1]] * r.window_quantums[1];
58 | aggreated_capacity += capacity_log[r.window_idxs[2]] * r.window_quantums[2];
59 | aggreated_capacity /= workload.frame_quantum_;
60 | render_lag_seq.push_back(calc_lag(r.frame_load, aggreated_capacity));
61 | }
62 |
63 | double common_lag_ratio = PerfPartitionEval(common_lag_seq);
64 | double render_lag_ratio = PerfPartitionEval(render_lag_seq);
65 |
66 | double score = misc_.render_fraction * render_lag_ratio + misc_.common_fraction * common_lag_ratio;
67 | // double score = render_lag_ratio;
68 |
69 | return (score / default_score_.performance);
70 | }
71 |
72 | double Rank::PerfPartitionEval(const LagSeq &lag_seq) const {
73 | const int partition_len = misc_.perf_partition_len;
74 | const int n_partition = lag_seq.size() / partition_len;
75 |
76 | const int &seq_lag_l1 = misc_.seq_lag_l1;
77 | const int &seq_lag_l2 = misc_.seq_lag_l2;
78 | const int &seq_lag_max = misc_.seq_lag_max;
79 |
80 | const double &seq_l0_scale = misc_.seq_lag_l0_scale;
81 | const double &seq_l1_scale = misc_.seq_lag_l1_scale;
82 | const double &seq_l2_scale = misc_.seq_lag_l2_scale;
83 |
84 | LagSeq period_lag_arr;
85 | period_lag_arr.reserve(n_partition);
86 |
87 | int cnt = 1;
88 | int n_recent_lag = 0;
89 | float period_lag_score = 0.0;
90 | for (const auto &lag_scale : lag_seq) {
91 | bool is_lag = (lag_scale > 0);
92 | if (cnt == partition_len) {
93 | period_lag_arr.push_back(period_lag_score);
94 | period_lag_score = 0.0;
95 | cnt = 0;
96 | }
97 | if (!is_lag) {
98 | n_recent_lag = n_recent_lag >> 1;
99 | }
100 | n_recent_lag = std::min(seq_lag_max, n_recent_lag + is_lag);
101 |
102 | period_lag_score += seq_l0_scale * lag_scale * (n_recent_lag > 0);
103 | period_lag_score += seq_l1_scale * lag_scale * (n_recent_lag >= seq_lag_l1);
104 | period_lag_score += seq_l2_scale * lag_scale * (n_recent_lag >= seq_lag_l2);
105 | ++cnt;
106 | }
107 |
108 | double sum = 0;
109 | for (const auto &l : period_lag_arr) {
110 | sum += l * l;
111 | }
112 |
113 | return std::sqrt(sum / n_partition);
114 | }
115 |
116 | double Rank::EvalBatterylife(const SimSeq &power_log) const {
117 | double partitional = BattPartitionEval(power_log);
118 | return (1.0 / (partitional * default_score_.battery_life));
119 | }
120 |
121 | double Rank::BattPartitionEval(const SimSeq &power_seq) const {
122 | const int partition_len = misc_.batt_partition_len;
123 | const int n_partition = power_seq.size() / partition_len;
124 |
125 | std::vector period_power_arr;
126 | period_power_arr.reserve(n_partition);
127 |
128 | int cnt = 1;
129 | uint64_t period_power_comsumed = 0;
130 | for (const auto &power_comsumed : power_seq) {
131 | if (cnt == partition_len) {
132 | period_power_arr.push_back(period_power_comsumed);
133 | period_power_comsumed = 0;
134 | cnt = 0;
135 | }
136 | period_power_comsumed += power_comsumed;
137 | ++cnt;
138 | }
139 |
140 | double sum = 0;
141 | for (int i = 0; i < n_partition; ++i) {
142 | double t = (double)period_power_arr[i] / default_score_.ref_power_comsumed[i];
143 | sum += t * t;
144 | }
145 |
146 | return std::sqrt(sum / n_partition);
147 | }
148 |
149 | std::vector Rank::InitRefBattPartition(const SimSeq &power_seq) const {
150 | const int partition_len = misc_.batt_partition_len;
151 | const int n_partition = power_seq.size() / partition_len;
152 |
153 | std::vector period_power_arr;
154 | period_power_arr.reserve(n_partition);
155 |
156 | int cnt = 1;
157 | uint64_t period_power_comsumed = 0;
158 | for (const auto &power_comsumed : power_seq) {
159 | if (cnt == partition_len) {
160 | period_power_arr.push_back(period_power_comsumed);
161 | period_power_comsumed = 0;
162 | cnt = 0;
163 | }
164 | period_power_comsumed += power_comsumed;
165 | ++cnt;
166 | }
167 |
168 | return period_power_arr;
169 | }
170 |
171 | // double Rank::CalcComplexity(const Interactive &little, const Interactive &big) const {
172 | // const int kAboveMinLen = 10;
173 | // const int kTargetloadMinLen = 10;
174 |
175 | // double clpx[4] = {0.0, 0.0, 0.0, 0.0};
176 | // int i = 0;
177 |
178 | // clpx[i++] = std::max(kAboveMinLen, little.GetAboveHispeedDelayGearNum()) / (double)kAboveMinLen;
179 | // clpx[i++] = std::max(kTargetloadMinLen, little.GetTargetLoadGearNum()) / (double)kTargetloadMinLen;
180 | // clpx[i++] = std::max(kAboveMinLen, big.GetAboveHispeedDelayGearNum()) / (double)kAboveMinLen;
181 | // clpx[i++] = std::max(kTargetloadMinLen, big.GetTargetLoadGearNum()) / (double)kTargetloadMinLen;
182 |
183 | // double sum = 0.0;
184 | // for (const auto &n : clpx) {
185 | // sum += n * n;
186 | // }
187 |
188 | // return std::sqrt(sum / 4);
189 | // }
190 |
--------------------------------------------------------------------------------
/source/sim/rank.h:
--------------------------------------------------------------------------------
1 | #ifndef __RANK_H
2 | #define __RANK_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include "cpumodel.h"
8 | #include "sim_types.h"
9 | #include "workload.h"
10 |
11 | // 评分
12 | class Rank {
13 | public:
14 | #define POWER_SHIFT 4
15 |
16 | typedef struct _Score {
17 | double performance;
18 | double battery_life;
19 | double idle_lasting;
20 | std::vector ref_power_comsumed;
21 | } Score;
22 |
23 | typedef struct _MiscConst {
24 | double render_fraction;
25 | double common_fraction;
26 | double complexity_fraction;
27 | int perf_partition_len;
28 | int seq_lag_l1;
29 | int seq_lag_l2;
30 | int seq_lag_max;
31 | double seq_lag_l0_scale;
32 | double seq_lag_l1_scale;
33 | double seq_lag_l2_scale;
34 | double enough_penalty;
35 | int batt_partition_len;
36 | } MiscConst;
37 |
38 | using LagSeq = std::vector;
39 |
40 | Rank() = delete;
41 | Rank(const Score &default_score, const MiscConst &misc) : misc_(misc), default_score_(default_score){};
42 | Score Eval(const Workload &workload, const Workload &idleload, const SimResultPack &rp, Soc soc, bool is_init);
43 |
44 | private:
45 | int QuantifyPower(int power) const { return (power >> POWER_SHIFT); }
46 |
47 | void AdaptLoad(int &load, int capacity) const { load = std::min(load, capacity); }
48 | void AdaptLoad(int *loads, int n_loads, int capacity) const {
49 | for (int i = 0; i < n_loads; ++i) {
50 | loads[i] = std::min(loads[i], capacity);
51 | }
52 | }
53 |
54 | double PerfPartitionEval(const LagSeq &lag_seq) const;
55 | double BattPartitionEval(const SimSeq &power_seq) const;
56 |
57 | double EvalPerformance(const Workload &workload, const Soc &soc, const SimSeq &capacity_log);
58 | double EvalBatterylife(const SimSeq &power_log) const;
59 |
60 | std::vector InitRefBattPartition(const SimSeq &power_seq) const;
61 |
62 | double EvalIdleLasting(uint64_t idle_power_comsumed) const {
63 | return (1.0 / (idle_power_comsumed * default_score_.idle_lasting));
64 | }
65 |
66 | MiscConst misc_;
67 | Score default_score_;
68 | };
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/source/sim/sim.hpp:
--------------------------------------------------------------------------------
1 | #ifndef __SIM_H
2 | #define __SIM_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include "cpumodel.h"
11 | #include "sim_types.h"
12 | #include "workload.h"
13 |
14 | template
15 | struct GovernorTs {
16 | typename GovernorT::Tunables t[2];
17 | };
18 |
19 | // 仿真运行
20 | template
21 | class Sim {
22 | public:
23 | #define POWER_SHIFT 4
24 |
25 | typedef struct _Tunables {
26 | GovernorTs governor;
27 | typename SchedT::Tunables sched;
28 | typename BoostT::Tunables boost;
29 | bool has_boost;
30 | } Tunables;
31 |
32 | typedef struct _MiscConst {
33 | int working_base_mw;
34 | int idle_base_mw;
35 | } MiscConst;
36 |
37 | using Governor = GovernorT;
38 | using Sched = SchedT;
39 | using Boost = BoostT;
40 |
41 | Sim() = delete;
42 | Sim(const Tunables &tunables, const MiscConst &misc) : tunables_(tunables), misc_(misc){};
43 |
44 | // 仿真运行,得到亮屏考察每一时间片的性能输出和功耗,以及灭屏的总耗电
45 | void Run(const Workload &workload, const Workload &idleload, Soc soc, SimResultPack *rp) {
46 | // 常量计算
47 | const int cl_little_idx = soc.GetLittleClusterIdx();
48 | const int cl_big_idx = soc.GetBigClusterIdx();
49 | const int base_pwr = misc_.working_base_mw * 100;
50 | const int idle_base_pwr = misc_.idle_base_mw * 100;
51 |
52 | // 使用参数实例化CPU调速器仿真
53 | auto little_governor = GovernorT(tunables_.governor.t[cl_little_idx], &soc.clusters_[cl_little_idx]);
54 | auto big_governor = GovernorT(tunables_.governor.t[cl_big_idx], &soc.clusters_[cl_big_idx]);
55 |
56 | // 使用参数实例化调度器仿真
57 | typename SchedT::Cfg sched_cfg;
58 | sched_cfg.tunables = tunables_.sched;
59 | sched_cfg.little = &soc.clusters_[cl_little_idx];
60 | sched_cfg.big = &soc.clusters_[cl_big_idx];
61 | sched_cfg.governor_little = &little_governor;
62 | sched_cfg.governor_big = &big_governor;
63 | SchedT sched(sched_cfg);
64 |
65 | // 使用参数实例化输入升频
66 | BoostT boost;
67 | if (tunables_.has_boost) {
68 | typename BoostT::SysEnv boost_env;
69 | boost_env.soc = &soc;
70 | boost_env.little = &little_governor;
71 | boost_env.big = &big_governor;
72 | boost_env.sched = &sched;
73 | boost = BoostT(tunables_.boost, boost_env);
74 | }
75 |
76 | int quantum_cnt = 0;
77 | int capacity = soc.clusters_[0].CalcCapacity();
78 |
79 | // 亮屏考察每一时间片的性能输出和功耗
80 | auto &capacity_log = rp->onscreen.capacity;
81 | auto &power_log = rp->onscreen.power;
82 | for (Workload::LoadSlice w : workload.windowed_load_) {
83 | AdaptLoad(w.max_load, capacity);
84 | AdaptLoad(w.load, workload.core_num_, capacity);
85 | capacity_log.push_back(capacity);
86 | power_log.push_back(base_pwr + sched.CalcPower(w.load));
87 |
88 | boost.Tick(w.has_input_event, w.has_render, quantum_cnt);
89 | capacity = sched.SchedulerTick(w.max_load, w.load, workload.core_num_, quantum_cnt);
90 | quantum_cnt++;
91 | }
92 |
93 | // 灭屏只计算耗电总和,不考察是否卡顿
94 | rp->offscreen_pwr = idle_base_pwr * idleload.windowed_load_.size();
95 | for (Workload::LoadSlice w : idleload.windowed_load_) {
96 | AdaptLoad(w.max_load, capacity);
97 | AdaptLoad(w.load, idleload.core_num_, capacity);
98 | rp->offscreen_pwr += sched.CalcPowerForIdle(w.load);
99 |
100 | boost.Tick(w.has_input_event, w.has_render, quantum_cnt);
101 | capacity = sched.SchedulerTick(w.max_load, w.load, idleload.core_num_, quantum_cnt);
102 | quantum_cnt++;
103 | }
104 |
105 | return;
106 | }
107 |
108 | private:
109 | // 根据当前性能输出限幅输入的性能需求,不可能输入高于100%的负载
110 | void AdaptLoad(int &load, int capacity) const { load = std::min(load, capacity); }
111 | // 根据当前性能输出限幅输入的性能需求,不可能输入高于100%的负载
112 | void AdaptLoad(int *loads, int n_loads, int capacity) const {
113 | for (int i = 0; i < n_loads; ++i) {
114 | loads[i] = std::min(loads[i], capacity);
115 | }
116 | }
117 |
118 | Tunables tunables_;
119 | MiscConst misc_;
120 | };
121 |
122 | #endif
123 |
--------------------------------------------------------------------------------
/source/sim/sim_types.h:
--------------------------------------------------------------------------------
1 | #ifndef __SIM_TYPES_H
2 | #define __SIM_TYPES_H
3 |
4 | #include
5 | #include
6 |
7 | typedef std::vector SimSeq;
8 |
9 | typedef struct _SimResult {
10 | SimSeq capacity;
11 | SimSeq power;
12 | } SimResult;
13 |
14 | typedef struct _SimResultPack {
15 | SimResult onscreen;
16 | uint64_t offscreen_pwr;
17 | } SimResultPack;
18 |
19 | #endif
20 |
--------------------------------------------------------------------------------
/source/sim/workload.cpp:
--------------------------------------------------------------------------------
1 | #include "workload.h"
2 |
3 | #include
4 | #include
5 |
6 | #include "json.hpp"
7 |
8 | Workload::Workload(const std::string &workload_file) {
9 | std::ifstream ifs(workload_file);
10 | if (!ifs.good()) {
11 | using namespace std;
12 | cout << "Workload access ERROR: " << workload_file << endl;
13 | throw runtime_error("file access error");
14 | }
15 |
16 | nlohmann::json j;
17 | ifs >> j;
18 | quantum_sec_ = j["quantumSec"];
19 | window_quantum_ = j["windowQuantum"];
20 | frame_quantum_ = j["frameQuantum"];
21 | efficiency_ = j["efficiency"];
22 | freq_ = j["freq"];
23 | load_scale_ = j["loadScale"];
24 | core_num_ = j["coreNum"];
25 |
26 | for (const auto &src_name : j["src"]) {
27 | src_.push_back(src_name);
28 | }
29 |
30 | auto loadpct_to_demand = [=](int load) { return kWorkloadScaleFactor * freq_ * efficiency_ * load; };
31 |
32 | if (j["renderLoad"].size() == 0) {
33 | using namespace std;
34 | cout << "renderLoad is empty: " << workload_file << endl;
35 | throw runtime_error("renderLoad is empty");
36 | }
37 |
38 | auto next_win_q = [=](int q) { return (q / window_quantum_ + 1) * window_quantum_; };
39 | render_load_.reserve(j["renderLoad"].size());
40 | for (const auto &render_demand : j["renderLoad"]) {
41 | RenderSlice r;
42 | memset(&r, 0, sizeof(RenderSlice));
43 |
44 | int begin_q = render_demand[0];
45 | int end_q = begin_q + frame_quantum_;
46 | int idx_rec = 0;
47 | int left_q = begin_q;
48 | int right_q = next_win_q(begin_q);
49 | while (left_q != right_q) {
50 | r.window_idxs[idx_rec] = left_q / window_quantum_;
51 | r.window_quantums[idx_rec] = right_q - left_q;
52 | left_q = right_q;
53 | right_q = std::min(end_q, next_win_q(right_q));
54 | idx_rec++;
55 | }
56 | r.frame_load = loadpct_to_demand(render_demand[1]);
57 |
58 | render_load_.push_back(r);
59 | }
60 |
61 | if (j["windowedLoad"].size() == 0) {
62 | using namespace std;
63 | cout << "windowedLoad is empty: " << workload_file << endl;
64 | throw runtime_error("windowedLoad is empty");
65 | }
66 |
67 | auto has_render = [&](int idx) {
68 | for (const auto &r : render_load_) {
69 | if (r.window_idxs[0] == idx || r.window_idxs[1] == idx || r.window_idxs[2] == idx)
70 | return true;
71 | }
72 | return false;
73 | };
74 |
75 | windowed_load_.reserve(j["windowedLoad"].size());
76 | for (const auto &slice : j["windowedLoad"]) {
77 | LoadSlice l;
78 | memset(&l, 0, sizeof(LoadSlice));
79 |
80 | l.max_load = loadpct_to_demand(slice[0]);
81 | for (int idx = 0; idx < core_num_; ++idx) {
82 | l.load[idx] = loadpct_to_demand(slice[idx + 1]);
83 | }
84 | // 按降序排列,对于骁龙82x这种2+2的平台只会使用前2个负载值
85 | std::sort(&l.load[0], &l.load[3], std::greater());
86 | l.has_input_event = slice[core_num_ + 1];
87 | l.has_render = has_render(windowed_load_.size());
88 |
89 | windowed_load_.push_back(l);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/source/sim/workload.h:
--------------------------------------------------------------------------------
1 | #ifndef __WORKLOAD_H
2 | #define __WORKLOAD_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | class Workload {
10 | public:
11 | typedef struct _LoadSlice {
12 | int max_load;
13 | int load[4];
14 | int has_input_event;
15 | int has_render;
16 | } LoadSlice;
17 |
18 | typedef struct _RenderSlice {
19 | int window_idxs[3];
20 | int window_quantums[3];
21 | int frame_load;
22 | } RenderSlice;
23 |
24 | Workload(const std::string &workload_file);
25 |
26 | const float kWorkloadScaleFactor = 1.15;
27 | std::vector windowed_load_;
28 | std::vector render_load_;
29 | std::vector src_;
30 | float quantum_sec_;
31 | int window_quantum_;
32 | int frame_quantum_;
33 | int efficiency_;
34 | int freq_;
35 | int load_scale_;
36 | int core_num_;
37 |
38 | private:
39 | Workload();
40 | };
41 |
42 | #endif
--------------------------------------------------------------------------------
/source/utils/misc.h:
--------------------------------------------------------------------------------
1 | #ifndef __MISC_H
2 | #define __MISC_H
3 |
4 | #include
5 |
6 | inline int Ms2Us(int ms) {
7 | return (1000 * ms);
8 | }
9 |
10 | inline int Mhz2kHz(int mhz) {
11 | return (1000 * mhz);
12 | }
13 |
14 | inline double Double2Pct(double d) {
15 | return (d * 100);
16 | }
17 |
18 | inline int Quantum2Ms(int n_quantum) {
19 | return (n_quantum * 10);
20 | }
21 |
22 | inline bool Replace(std::string &str, const std::string &from, const std::string &to) {
23 | size_t start_pos = str.find(from);
24 | if (start_pos == std::string::npos)
25 | return false;
26 | str.replace(start_pos, from.length(), to);
27 | return true;
28 | }
29 |
30 | inline void ReplaceAll(std::string &str, const std::string &from, const std::string &to) {
31 | if (from.empty())
32 | return;
33 | size_t start_pos = 0;
34 | while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
35 | str.replace(start_pos, from.length(), to);
36 | start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
37 | }
38 | }
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/template/powercfg_template.sh:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 | # [project_name] [github_url]
3 | # Author: [yourname]
4 | # Platform: [platform_name]
5 | # Generated at: [generated_time]
6 |
7 | CUR_LEVEL_FILE="/cache/.wipe_cur_level"
8 | PARAM_BAK_FILE="/cache/.wipe_param_bak"
9 |
10 | # const variables
11 | PARAM_NUM=[param_num]
12 |
13 | # sysfs_objx example:
14 | # sysfs_obj1="${C0_GOVERNOR_DIR}/target_loads"
15 | [sysfs_obj]
16 |
17 | # level x example:
18 | # lag percent: 90.0%
19 | # battery life: 110.0%
20 | # levelx_val1="38000"
21 | # levelx_val2="85 1190000:90"
22 |
23 | # LEVEL 0
24 | [level0]
25 | # LEVEL 1
26 | [level1]
27 | # LEVEL 2
28 | [level2]
29 | # LEVEL 3
30 | [level3]
31 | # LEVEL 4
32 | [level4]
33 | # LEVEL 5
34 | [level5]
35 | # LEVEL 6
36 | [level6]
37 |
38 | # global variables
39 | HAS_BAK=0
40 | NOT_MATCH_NUM=0
41 |
42 | # $1:value $2:file path
43 | lock_value()
44 | {
45 | if [ -f ${2} ]; then
46 | chmod 0666 ${2}
47 | echo ${1} > ${2}
48 | chmod 0444 ${2}
49 | fi
50 | }
51 |
52 | # $1:level_number
53 | apply_level()
54 | {
55 | # 1. backup
56 | backup_default
57 | # 2. apply modification
58 | for n in `seq ${PARAM_NUM}`
59 | do
60 | eval obj="$"sysfs_obj${n}
61 | eval val="$"level${1}_val${n}
62 | lock_value "${val}" ${obj}
63 | done
64 | # 3. save current level to file
65 | echo ${1} > ${CUR_LEVEL_FILE}
66 | }
67 |
68 | # $1:value $2:file path
69 | check_value()
70 | {
71 | if [ -f ${2} ]; then
72 | expected="${1}"
73 | actual="`cat ${2}`"
74 | if [ "${actual}" != "${expected}" ]; then
75 | # input_boost_freq has a additional line break
76 | case1=$(echo "${actual}" | grep "${expected}")
77 | # Actual scaling_min_freq is 633600, but given is 633000. That's OK
78 | case2=$(echo "${2}" | grep -E "scaling_m.{2}_freq$")
79 | # skip msm_performance/parameters: cpu_min_freq and cpu_max_freq
80 | case3=$(echo "${2}" | grep -E "cpu_m.{2}_freq$")
81 | if [ "${case1}" == "" ] && [ "${case2}" == "" ] && [ "${case3}" == "" ]; then
82 | NOT_MATCH_NUM=$(expr ${NOT_MATCH_NUM} + 1)
83 | echo "[FAIL] ${2}"
84 | echo "expected: ${expected}"
85 | echo "actual: ${actual}"
86 | fi
87 | fi
88 | else
89 | echo "[IGNORE] ${2}"
90 | fi
91 | }
92 |
93 | # $1:level_number
94 | verify_level()
95 | {
96 | for n in `seq ${PARAM_NUM}`
97 | do
98 | eval obj="$"sysfs_obj${n}
99 | eval val="$"level${1}_val${n}
100 | check_value "${val}" ${obj}
101 | done
102 | echo "Verified ${PARAM_NUM} parameters, ${NOT_MATCH_NUM} FAIL"
103 | }
104 |
105 | backup_default()
106 | {
107 | if [ ${HAS_BAK} -eq 0 ]; then
108 | # clear previous backup file
109 | echo "" > ${PARAM_BAK_FILE}
110 | for n in `seq ${PARAM_NUM}`
111 | do
112 | eval obj="$"sysfs_obj${n}
113 | echo "bak_obj${n}=${obj}" >> ${PARAM_BAK_FILE}
114 | echo "bak_val${n}=\"`cat ${obj}`\"" >> ${PARAM_BAK_FILE}
115 | done
116 | echo "Backup default parameters has completed."
117 | else
118 | echo "Backup file already exists, skip backup."
119 | fi
120 | }
121 |
122 | restore_default()
123 | {
124 | if [ -f ${PARAM_BAK_FILE} ]; then
125 | # read backup variables
126 | while read line
127 | do
128 | eval ${line}
129 | done < ${PARAM_BAK_FILE}
130 | # set backup variables
131 | for n in `seq ${PARAM_NUM}`
132 | do
133 | eval obj="$"bak_obj${n}
134 | eval val="$"bak_val${n}
135 | lock_value "${val}" ${obj}
136 | done
137 | echo "Restore OK"
138 | else
139 | echo "Backup file for default parameters not found."
140 | echo "Restore FAIL"
141 | fi
142 | }
143 |
144 | permanently_disable_perfd()
145 | {
146 | stop perfd
147 | perfd_path=`which perfd`
148 | if [ -n "${perfd_path}" ]; then
149 | mv ${perfd_path} `dirname ${perfd_path}`/perfd_bak
150 | echo "Perfd has been disabled."
151 | else
152 | echo "Perfd binary not found."
153 | fi
154 | }
155 |
156 | permanently_enable_perfd()
157 | {
158 | perfd_bak_path=`which perfd_bak`
159 | if [ -n "${perfd_bak_path}" ]; then
160 | mv ${perfd_bak_path} `dirname ${perfd_bak_path}`/perfd
161 | echo "Perfd has been enabled."
162 | else
163 | echo "Perfd_bak binary not found."
164 | fi
165 | start perfd
166 | }
167 |
168 | # suppress stderr
169 | (
170 |
171 | echo ""
172 |
173 | # backup runonce flag
174 | if [ -f ${PARAM_BAK_FILE} ]; then
175 | HAS_BAK=1
176 | fi
177 |
178 | action=$1
179 | # default option is balance
180 | if [ ! -n "$action" ]; then
181 | action="balance"
182 | fi
183 |
184 | if [ "$action" = "debug" ]; then
185 | echo "[project_name] [github_url]"
186 | echo "Author: [yourname]"
187 | echo "Platform: [platform_name]"
188 | echo "Generated at: [generated_time]"
189 | echo ""
190 | # perform parameter verification
191 | cur_level=`cat ${CUR_LEVEL_FILE}`
192 | if [ -n "${cur_level}" ]; then
193 | echo "Current level: ${cur_level}"
194 | verify_level ${cur_level}
195 | else
196 | echo "Current level: not detected"
197 | fi
198 | echo ""
199 | exit 0
200 | fi
201 |
202 | if [ "$action" = "restore" ]; then
203 | restore_default
204 | rm ${CUR_LEVEL_FILE}
205 | fi
206 |
207 | if [ "$action" = "powersave" ]; then
208 | echo "Applying powersave..."
209 | apply_level 5
210 | echo "Applying powersave done."
211 | fi
212 |
213 | if [ "$action" = "balance" ]; then
214 | echo "Applying balance..."
215 | apply_level 3
216 | echo "Applying balance done."
217 | fi
218 |
219 | if [ "$action" = "performance" ]; then
220 | echo "Applying performance..."
221 | apply_level 1
222 | echo "Applying performance done."
223 | fi
224 |
225 | if [ "$action" = "fast" ]; then
226 | echo "Applying fast..."
227 | apply_level 0
228 | echo "Applying fast done."
229 | fi
230 |
231 | if [ "$action" = "level" ]; then
232 | level=${2}
233 | if [ "${level}" -ge "0" ] && [ "${level}" -le "6" ]; then
234 | echo "Applying level ${level}..."
235 | apply_level ${level}
236 | echo "Applying level ${level} done."
237 | else
238 | echo "Level ${level} not supported."
239 | fi
240 | fi
241 |
242 | if [ "$action" = "perfd" ]; then
243 | cmd=${2}
244 | if [ "${cmd}" == "enable" ]; then
245 | permanently_enable_perfd
246 | fi
247 | if [ "${cmd}" == "disable" ]; then
248 | permanently_disable_perfd
249 | fi
250 | fi
251 |
252 | echo ""
253 |
254 | # suppress stderr
255 | ) 2>/dev/null
256 |
257 | exit 0
258 |
--------------------------------------------------------------------------------
/tools/migrate.py:
--------------------------------------------------------------------------------
1 | import re
2 | import os
3 | import json
4 | import argparse
5 |
6 | need_merged_file = True
7 | raw_path = '../dataset/workload/osborn/raw/'
8 | out_path = '../dataset/workload/osborn/'
9 | n_cpu = 8
10 | trace_cpuid_low = 4
11 | trace_cpuid_high = 7
12 | # window_sec = 0.02 # 20ms timer_rate
13 | window_sec = 0.01 # 负载聚合到10ms,以适配10ms,20ms,30ms...的timer_rate
14 | quantum_sec = 0.001 # 解析序列的最小时间单位,我们不在意事件在1.2ms还是1.4ms发生的,1ms
15 | frame_sec = 0.016 # 1帧的时长,16.7ms归到16ms
16 |
17 | merged_load_seq = list()
18 | load_shift = 7
19 | load_scale = 100 # 满负载是100
20 | busy_ratio_to_load = lambda busy_ratio: int(round(busy_ratio * load_scale))
21 |
22 | info_filename = 'info.json'
23 | info = None
24 | with open(raw_path + info_filename, 'r') as filename:
25 | info = json.load(filename)
26 |
27 | # 采集设备是 nexus 9
28 | idle_efficiency = 1638
29 | idle_freq = 2014
30 |
31 | idle_load_seq = list()
32 | with open('standby_load_20180308_from_171023.csv', 'r') as f:
33 | for line in f:
34 | idle_load_seq.append(min(100, int(line) + 5))
35 |
36 | # 全长1000,取前800
37 | windowed_idle_load_seq = list()
38 | for demand in idle_load_seq:
39 | windowed_idle_load_seq.append([demand, demand, demand, demand, demand, 0])
40 |
41 | # 加一个触摸事件
42 | # windowed_idle_load_seq[400][-1] = 1
43 |
44 | packed_data = {
45 | 'src': 'standby_load_20180308_from_171023.csv',
46 | 'ver': 1,
47 | 'quantumSec': quantum_sec,
48 | 'windowQuantum': int(window_sec / quantum_sec),
49 | 'frameQuantum': int(frame_sec / quantum_sec),
50 | 'efficiencyA53': 1024,
51 | 'efficiency': info['efficiency'],
52 | 'freq': info['freq'],
53 | 'loadScale': load_scale,
54 | 'coreNum': trace_cpuid_high - trace_cpuid_low + 1,
55 | 'windowedLoadLen': len(windowed_idle_load_seq),
56 | 'windowedLoad': windowed_idle_load_seq,
57 | 'renderLoad': [[0, 0],]
58 | }
59 | with open(out_path + 'idle' + '.json', 'w') as f:
60 | json.dump(packed_data, f, indent=None, separators=(',', ':'))
61 |
62 |
--------------------------------------------------------------------------------
/tools/standby_load_20180308_from_171023.csv:
--------------------------------------------------------------------------------
1 | 5
2 | 0
3 | 5
4 | 0
5 | 5
6 | 9
7 | 0
8 | 0
9 | 10
10 | 4
11 | 5
12 | 0
13 | 13
14 | 0
15 | 0
16 | 10
17 | 0
18 | 9
19 | 0
20 | 14
21 | 0
22 | 15
23 | 15
24 | 4
25 | 20
26 | 42
27 | 5
28 | 5
29 | 0
30 | 0
31 | 4
32 | 5
33 | 0
34 | 18
35 | 0
36 | 0
37 | 0
38 | 0
39 | 5
40 | 0
41 | 0
42 | 10
43 | 4
44 | 5
45 | 0
46 | 10
47 | 15
48 | 13
49 | 0
50 | 19
51 | 0
52 | 10
53 | 0
54 | 5
55 | 0
56 | 5
57 | 5
58 | 9
59 | 0
60 | 13
61 | 4
62 | 5
63 | 5
64 | 0
65 | 0
66 | 0
67 | 5
68 | 5
69 | 0
70 | 5
71 | 5
72 | 5
73 | 9
74 | 0
75 | 5
76 | 5
77 | 10
78 | 9
79 | 0
80 | 10
81 | 0
82 | 0
83 | 10
84 | 5
85 | 5
86 | 9
87 | 5
88 | 9
89 | 5
90 | 0
91 | 0
92 | 4
93 | 5
94 | 9
95 | 5
96 | 5
97 | 9
98 | 10
99 | 5
100 | 4
101 | 9
102 | 5
103 | 20
104 | 0
105 | 5
106 | 47
107 | 0
108 | 0
109 | 4
110 | 15
111 | 4
112 | 5
113 | 5
114 | 0
115 | 9
116 | 5
117 | 0
118 | 9
119 | 5
120 | 0
121 | 0
122 | 4
123 | 5
124 | 10
125 | 9
126 | 5
127 | 0
128 | 5
129 | 4
130 | 5
131 | 4
132 | 0
133 | 0
134 | 5
135 | 14
136 | 9
137 | 5
138 | 5
139 | 0
140 | 25
141 | 5
142 | 5
143 | 47
144 | 0
145 | 5
146 | 0
147 | 0
148 | 14
149 | 13
150 | 5
151 | 5
152 | 5
153 | 4
154 | 5
155 | 0
156 | 4
157 | 5
158 | 0
159 | 5
160 | 0
161 | 5
162 | 9
163 | 5
164 | 0
165 | 10
166 | 0
167 | 4
168 | 5
169 | 0
170 | 0
171 | 5
172 | 9
173 | 0
174 | 9
175 | 5
176 | 0
177 | 13
178 | 0
179 | 4
180 | 5
181 | 5
182 | 10
183 | 11
184 | 0
185 | 47
186 | 25
187 | 14
188 | 13
189 | 0
190 | 0
191 | 9
192 | 0
193 | 5
194 | 4
195 | 5
196 | 4
197 | 0
198 | 0
199 | 13
200 | 14
201 | 0
202 | 5
203 | 5
204 | 13
205 | 5
206 | 0
207 | 5
208 | 5
209 | 4
210 | 9
211 | 0
212 | 4
213 | 10
214 | 14
215 | 4
216 | 0
217 | 5
218 | 5
219 | 5
220 | 0
221 | 5
222 | 4
223 | 5
224 | 9
225 | 10
226 | 0
227 | 9
228 | 5
229 | 5
230 | 9
231 | 5
232 | 0
233 | 0
234 | 5
235 | 4
236 | 0
237 | 4
238 | 5
239 | 13
240 | 10
241 | 5
242 | 0
243 | 0
244 | 5
245 | 4
246 | 5
247 | 0
248 | 5
249 | 10
250 | 5
251 | 9
252 | 5
253 | 4
254 | 5
255 | 9
256 | 10
257 | 0
258 | 5
259 | 5
260 | 25
261 | 5
262 | 9
263 | 61
264 | 5
265 | 9
266 | 9
267 | 5
268 | 5
269 | 0
270 | 0
271 | 5
272 | 0
273 | 4
274 | 0
275 | 9
276 | 17
277 | 0
278 | 9
279 | 0
280 | 5
281 | 0
282 | 0
283 | 13
284 | 0
285 | 5
286 | 5
287 | 0
288 | 5
289 | 5
290 | 9
291 | 17
292 | 0
293 | 0
294 | 13
295 | 0
296 | 5
297 | 15
298 | 15
299 | 5
300 | 33
301 | 30
302 | 13
303 | 9
304 | 0
305 | 10
306 | 0
307 | 0
308 | 5
309 | 4
310 | 0
311 | 0
312 | 14
313 | 0
314 | 0
315 | 10
316 | 0
317 | 5
318 | 5
319 | 10
320 | 5
321 | 0
322 | 0
323 | 5
324 | 0
325 | 10
326 | 4
327 | 5
328 | 0
329 | 0
330 | 10
331 | 0
332 | 4
333 | 14
334 | 10
335 | 11
336 | 10
337 | 22
338 | 80
339 | 0
340 | 0
341 | 0
342 | 14
343 | 9
344 | 9
345 | 9
346 | 0
347 | 5
348 | 9
349 | 5
350 | 5
351 | 0
352 | 4
353 | 0
354 | 9
355 | 0
356 | 5
357 | 0
358 | 0
359 | 14
360 | 0
361 | 5
362 | 0
363 | 5
364 | 5
365 | 13
366 | 10
367 | 0
368 | 15
369 | 5
370 | 0
371 | 42
372 | 11
373 | 0
374 | 5
375 | 9
376 | 10
377 | 0
378 | 5
379 | 5
380 | 13
381 | 5
382 | 4
383 | 9
384 | 5
385 | 5
386 | 0
387 | 5
388 | 0
389 | 5
390 | 4
391 | 5
392 | 9
393 | 0
394 | 5
395 | 4
396 | 0
397 | 10
398 | 0
399 | 0
400 | 5
401 | 9
402 | 5
403 | 15
404 | 5
405 | 5
406 | 25
407 | 5
408 | 0
409 | 5
410 | 0
411 | 5
412 | 5
413 | 0
414 | 10
415 | 0
416 | 0
417 | 13
418 | 5
419 | 0
420 | 15
421 | 0
422 | 18
423 | 0
424 | 0
425 | 0
426 | 5
427 | 5
428 | 5
429 | 15
430 | 10
431 | 9
432 | 25
433 | 0
434 | 0
435 | 0
436 | 0
437 | 9
438 | 10
439 | 5
440 | 5
441 | 0
442 | 9
443 | 5
444 | 9
445 | 0
446 | 9
447 | 0
448 | 5
449 | 0
450 | 5
451 | 5
452 | 15
453 | 10
454 | 9
455 | 27
456 | 14
457 | 0
458 | 0
459 | 9
460 | 5
461 | 5
462 | 5
463 | 0
464 | 0
465 | 0
466 | 43
467 | 5
468 | 9
469 | 0
470 | 4
471 | 9
472 | 0
473 | 0
474 | 9
475 | 0
476 | 4
477 | 0
478 | 5
479 | 5
480 | 5
481 | 14
482 | 0
483 | 10
484 | 4
485 | 9
486 | 0
487 | 5
488 | 10
489 | 5
490 | 0
491 | 5
492 | 0
493 | 10
494 | 10
495 | 4
496 | 9
497 | 0
498 | 4
499 | 5
500 | 0
501 | 5
502 | 5
503 | 10
504 | 5
505 | 5
506 | 14
507 | 14
508 | 10
509 | 9
510 | 0
511 | 5
512 | 5
513 | 0
514 | 0
515 | 9
516 | 0
517 | 5
518 | 13
519 | 18
520 | 10
521 | 0
522 | 13
523 | 0
524 | 5
525 | 0
526 | 5
527 | 5
528 | 10
529 | 5
530 | 5
531 | 18
532 | 14
533 | 10
534 | 19
535 | 5
536 | 5
537 | 13
538 | 0
539 | 0
540 | 5
541 | 5
542 | 10
543 | 10
544 | 14
545 | 14
546 | 14
547 | 5
548 | 9
549 | 15
550 | 5
551 | 5
552 | 5
553 | 0
554 | 5
555 | 9
556 | 5
557 | 14
558 | 13
559 | 10
560 | 5
561 | 14
562 | 5
563 | 10
564 | 5
565 | 0
566 | 5
567 | 9
568 | 10
569 | 5
570 | 14
571 | 18
572 | 9
573 | 10
574 | 10
575 | 5
576 | 5
577 | 5
578 | 0
579 | 5
580 | 5
581 | 10
582 | 14
583 | 10
584 | 9
585 | 14
586 | 14
587 | 9
588 | 0
589 | 0
590 | 10
591 | 0
592 | 5
593 | 0
594 | 27
595 | 5
596 | 18
597 | 10
598 | 10
599 | 9
600 | 5
601 | 5
602 | 13
603 | 0
604 | 5
605 | 5
606 | 5
607 | 14
608 | 19
609 | 14
610 | 14
611 | 5
612 | 14
613 | 10
614 | 15
615 | 0
616 | 10
617 | 5
618 | 5
619 | 5
620 | 15
621 | 5
622 | 21
623 | 5
624 | 15
625 | 0
626 | 10
627 | 5
628 | 5
629 | 10
630 | 10
631 | 15
632 | 15
633 | 10
634 | 23
635 | 19
636 | 5
637 | 9
638 | 5
639 | 5
640 | 15
641 | 0
642 | 10
643 | 5
644 | 10
645 | 10
646 | 5
647 | 14
648 | 14
649 | 15
650 | 5
651 | 9
652 | 0
653 | 14
654 | 10
655 | 0
656 | 0
657 | 10
658 | 5
659 | 14
660 | 5
661 | 10
662 | 10
663 | 0
664 | 0
665 | 10
666 | 5
667 | 5
668 | 5
669 | 5
670 | 15
671 | 15
672 | 9
673 | 19
674 | 9
675 | 0
676 | 10
677 | 5
678 | 5
679 | 5
680 | 0
681 | 10
682 | 5
683 | 5
684 | 10
685 | 10
686 | 10
687 | 0
688 | 14
689 | 5
690 | 9
691 | 0
692 | 5
693 | 0
694 | 5
695 | 0
696 | 5
697 | 10
698 | 10
699 | 13
700 | 5
701 | 10
702 | 5
703 | 10
704 | 5
705 | 0
706 | 0
707 | 0
708 | 0
709 | 4
710 | 10
711 | 10
712 | 5
713 | 14
714 | 10
715 | 10
716 | 5
717 | 9
718 | 0
719 | 5
720 | 14
721 | 5
722 | 10
723 | 5
724 | 21
725 | 5
726 | 0
727 | 5
728 | 14
729 | 5
730 | 14
731 | 5
732 | 5
733 | 5
734 | 0
735 | 10
736 | 13
737 | 10
738 | 10
739 | 5
740 | 10
741 | 0
742 | 5
743 | 0
744 | 18
745 | 0
746 | 14
747 | 5
748 | 10
749 | 14
750 | 20
751 | 0
752 | 14
753 | 10
754 | 0
755 | 10
756 | 5
757 | 0
758 | 10
759 | 10
760 | 5
761 | 10
762 | 14
763 | 5
764 | 5
765 | 9
766 | 0
767 | 10
768 | 0
769 | 5
770 | 0
771 | 10
772 | 14
773 | 9
774 | 19
775 | 5
776 | 5
777 | 10
778 | 0
779 | 5
780 | 5
781 | 15
782 | 0
783 | 5
784 | 0
785 | 10
786 | 14
787 | 14
788 | 5
789 | 5
790 | 0
791 | 5
792 | 15
793 | 5
794 | 5
795 | 14
796 | 0
797 | 10
798 | 5
799 | 10
800 | 10
801 | 5
802 | 5
803 | 10
804 | 5
805 | 5
806 | 14
807 | 14
808 | 10
809 | 9
810 | 0
811 | 5
812 | 5
813 | 0
814 | 0
815 | 9
816 | 0
817 | 5
818 | 13
819 | 18
820 | 10
821 | 0
822 | 13
823 | 0
824 | 5
825 | 0
826 | 5
827 | 5
828 | 10
829 | 5
830 | 5
831 | 18
832 | 14
833 | 10
834 | 19
835 | 5
836 | 5
837 | 13
838 | 0
839 | 0
840 | 5
841 | 5
842 | 10
843 | 10
844 | 14
845 | 14
846 | 14
847 | 5
848 | 9
849 | 15
850 | 5
851 | 5
852 | 5
853 | 0
854 | 5
855 | 9
856 | 5
857 | 14
858 | 13
859 | 10
860 | 5
861 | 14
862 | 5
863 | 10
864 | 5
865 | 0
866 | 5
867 | 9
868 | 10
869 | 5
870 | 14
871 | 18
872 | 9
873 | 10
874 | 10
875 | 5
876 | 5
877 | 5
878 | 0
879 | 5
880 | 5
881 | 10
882 | 14
883 | 10
884 | 9
885 | 14
886 | 14
887 | 9
888 | 0
889 | 0
890 | 10
891 | 0
892 | 5
893 | 0
894 | 27
895 | 5
896 | 18
897 | 10
898 | 10
899 | 9
900 | 5
901 | 5
902 | 13
903 | 0
904 | 5
905 | 5
906 | 5
907 | 14
908 | 19
909 | 14
910 | 14
911 | 5
912 | 14
913 | 10
914 | 15
915 | 0
916 | 10
917 | 5
918 | 5
919 | 5
920 | 15
921 | 5
922 | 21
923 | 5
924 | 15
925 | 0
926 | 10
927 | 5
928 | 5
929 | 10
930 | 10
931 | 15
932 | 15
933 | 10
934 | 23
935 | 19
936 | 5
937 | 9
938 | 5
939 | 5
940 | 15
941 | 0
942 | 10
943 | 5
944 | 10
945 | 10
946 | 5
947 | 14
948 | 14
949 | 15
950 | 5
951 | 9
952 | 0
953 | 14
954 | 10
955 | 0
956 | 0
957 | 10
958 | 5
959 | 14
960 | 5
961 | 10
962 | 10
963 | 0
964 | 0
965 | 10
966 | 5
967 | 5
968 | 5
969 | 5
970 | 15
971 | 15
972 | 9
973 | 19
974 | 9
975 | 0
976 | 10
977 | 5
978 | 5
979 | 5
980 | 0
981 | 10
982 | 5
983 | 5
984 | 10
985 | 10
986 | 10
987 | 0
988 | 14
989 | 5
990 | 9
991 | 0
992 | 5
993 | 0
994 | 5
995 | 0
996 | 5
997 | 10
998 | 10
999 | 13
1000 | 5
1001 |
--------------------------------------------------------------------------------
/tools/tracefile_parse.py:
--------------------------------------------------------------------------------
1 | import re
2 | import os
3 | import json
4 | import argparse
5 |
6 | need_merged_file = True
7 | raw_path = '../dataset/workload/osborn/raw/'
8 | out_path = '../dataset/workload/osborn/'
9 | n_cpu = 8
10 | trace_cpuid_low = 4
11 | trace_cpuid_high = 7
12 | # window_sec = 0.02 # 20ms timer_rate
13 | window_sec = 0.01 # 负载聚合到10ms,以适配10ms,20ms,30ms...的timer_rate
14 | quantum_sec = 0.001 # 解析序列的最小时间单位,我们不在意事件在1.2ms还是1.4ms发生的,1ms
15 | frame_sec = 0.016 # 1帧的时长,16.7ms归到16ms
16 |
17 | merged_load_seq = list()
18 | load_shift = 7
19 | load_scale = 100 # 满负载是100
20 | busy_ratio_to_load = lambda busy_ratio: int(round(busy_ratio * load_scale))
21 |
22 | # 提取cpu c-state信息
23 | r_idle = r'^ {10}<.{20}\[(\d{3})\].{6}(\d+.\d{6}): cpu_idle: state=(\d{1,10}) '
24 | re_idle = re.compile(r_idle, re.MULTILINE)
25 |
26 | def parse_cstate(systrace, start_time_sec):
27 | t = re_idle.findall(systrace)
28 | idle_trace = [(int(cpuid), float(time), int(state)) for cpuid, time, state in t]
29 |
30 | # https://www.kernel.org/doc/Documentation/trace/events-power.txt
31 | # cpu_idle "state=%lu cpu_id=%lu"
32 | # Note: the value of "-1" or "4294967295" for state means an exit from the current state,
33 | CSTATE_EXIT = 4294967295
34 | # 准备进入cstate的犹豫时间,40us来自/sys/devices/system/cpu/cpu4/cpuidle/state0/latency
35 | WAIT_TO_SEE_SEC = 0.000040
36 | # cstate = 0 -> C1, cstate = 2 -> C3
37 | is_busy = lambda cstate: cstate == CSTATE_EXIT
38 | cstates = [999] * n_cpu
39 | cstates_start = [start_time_sec] * n_cpu
40 | busy_durations = [0.0] * n_cpu
41 | busy_seq = []
42 | window_start = start_time_sec
43 |
44 | for cpuid, time, state in idle_trace:
45 | # quantum时间截止,回写cpu busy时间
46 | while time - window_start > quantum_sec:
47 | window_start += quantum_sec
48 | for i in range(n_cpu):
49 | if is_busy(cstates[i]):
50 | busy_durations[i] = busy_durations[i] + window_start - cstates_start[i]
51 | cstates_start[i] = window_start
52 | busy_seq.append(tuple(busy_durations))
53 | for i in range(n_cpu):
54 | busy_durations[i] = 0.0
55 |
56 | if is_busy(cstates[cpuid]):
57 | delta = time - cstates_start[cpuid] - WAIT_TO_SEE_SEC
58 | busy_durations[cpuid] = max(0.0, busy_durations[cpuid] + delta)
59 | cstates[cpuid] = state
60 | cstates_start[cpuid] = time
61 |
62 | # 按照window_sec长度聚集负载
63 | n_quantum = int(window_sec / quantum_sec)
64 | windowed_load_seq = []
65 | sum_busy = [0.0] * n_cpu
66 | for idx in range(len(busy_seq)):
67 | for cpuid in range(n_cpu):
68 | sum_busy[cpuid] += busy_seq[idx][cpuid]
69 | # 如果在循环结束时有不完整的windowed_load,丢弃
70 | if idx % n_quantum == n_quantum - 1:
71 | windowed_loads = [busy_ratio_to_load(busy / window_sec) for busy in sum_busy]
72 | windowed_load_seq.append(windowed_loads)
73 | sum_busy = [0.0] * n_cpu
74 |
75 | # 传递给interactive调速器的会是集群中负载最大的数字
76 | max_load_seq = [max(loads[trace_cpuid_low: trace_cpuid_high+1]) for loads in windowed_load_seq]
77 |
78 | return max_load_seq, windowed_load_seq, busy_seq
79 |
80 |
81 | # 提取触摸响应,需要quantum时间进行聚集
82 | r_input = r'^.{20,45} (\d{1,10}.\d{6}):.+?\|pokeUserActivity'
83 | re_input = re.compile(r_input, re.MULTILINE)
84 |
85 | def parse_input(systrace, start_time_sec):
86 | t = re_input.findall(systrace)
87 | input_trace = [(float(x) - start_time_sec) for x in t]
88 | ret = set([int(time / window_sec) * window_sec for time in input_trace])
89 | ret = sorted(list(ret))
90 | return ret
91 |
92 |
93 | # 提取渲染帧起始时间,ui_thread为帧事件起始时间,按照input事件响应的app进行跟踪
94 | # 后台不交互的也会有ui渲染线程在活动,频率甚至可以很高(16ms),我们只关注前台用户正在使用的进程
95 | r_ui_thread = r'^.{20,45} (\d{1,10}.\d{6}).{23}\|(\d{3,6})\|Choreographer#doFrame'
96 | re_ui_thread = re.compile(r_ui_thread, re.MULTILINE)
97 | r_input_ui = r'^.{20,45} (\d{1,10}.\d{6}).{23}\|(\d{3,6})\|deliverInputEvent'
98 | re_input_ui = re.compile(r_input_ui, re.MULTILINE)
99 |
100 | def parse_render(systrace, start_time_sec):
101 | t = re_ui_thread.findall(systrace)
102 | ui_trace = [(float(time) - start_time_sec, int(pid)) for time, pid in t]
103 | t = re_input_ui.findall(systrace)
104 | ui_input_trace = [(float(time) - start_time_sec, int(pid)) for time, pid in t]
105 |
106 | # 提取当前交互在哪个进程发生,记录开始时间和进程PID
107 | input_log = []
108 | if len(ui_input_trace) > 0:
109 | input_log.append((0.0, ui_input_trace[0][1]))
110 | for time, pid in ui_input_trace:
111 | t = time - input_log[-1][0]
112 | # 至少等待16ms再切换当前交互的进程
113 | if not pid == input_log[-1][1] and t > frame_sec:
114 | input_log.append((time, pid))
115 | input_log.append((999999, 0))
116 |
117 | # 提取帧渲染开始的时间,用于辅助流畅度评分
118 | ret = []
119 | idx_input_log = 0
120 | prev_time = 0.0
121 | for time, pid in ui_trace:
122 | # 按照之前的结果,跳过并非前台交互程序的UI起始标志
123 | if input_log:
124 | if time > input_log[idx_input_log + 1][0]:
125 | idx_input_log += 1
126 | if not pid == input_log[idx_input_log][1]:
127 | continue
128 | delta = time - prev_time
129 | # 避免帧渲染请求太过重叠,进行没必要的卡顿评测
130 | # 跳过断断续续渲染请求的第一帧,通常这个负载相比之前的变化很大,不算在卡顿评测内
131 | if delta > 0.6 * frame_sec and delta < 5 * frame_sec:
132 | ret.append(int(round(time / quantum_sec)) * quantum_sec)
133 | prev_time = time
134 | return ret
135 |
136 |
137 | # 按照DOM标签提取原始trace信息
138 | r_tracedata = r'^ '
139 | re_tracedata = re.compile(r_tracedata, re.MULTILINE | re.DOTALL)
140 |
141 | # 提取起始时间戳
142 | r_starttime = r'^.{42}(\d{1,10}.\d{6}):'
143 | re_starttime = re.compile(r_starttime, re.MULTILINE)
144 |
145 | def parse_trace(input_file):
146 | print('processing', input_file)
147 | trace_datas = None
148 | with open(input_file, 'r') as f:
149 | content = f.read()
150 | trace_datas = re_tracedata.findall(content)
151 |
152 | if not trace_datas:
153 | print('load err')
154 | return
155 |
156 | # trace-data 标签数据块共有3个,第一个是进程信息,第二个是systrace,第三个是录制trace的命令行
157 | systrace = trace_datas[1]
158 | start_time_sec = float(re_starttime.findall(systrace, 0, 2000)[0])
159 |
160 | # 原始数据预处理
161 | max_load_seq, windowed_load_seq, busy_seq = parse_cstate(systrace, start_time_sec)
162 | input_seq = parse_input(systrace, start_time_sec)
163 | render_seq = parse_render(systrace, start_time_sec)
164 |
165 | # CPU4-7的最大负载,CPU4负载,CPU5负载,CPU6负载,CPU7负载,是否有触摸事件
166 | packed_loads_seq = []
167 | input_quantum_set = set([int(ftime / quantum_sec) for ftime in input_seq])
168 | n_window_quantum = int(window_sec / quantum_sec)
169 | time_quantum = 0.0
170 | for max_load, loads in zip(max_load_seq, windowed_load_seq):
171 | has_input_event = int(time_quantum in input_quantum_set)
172 | time_quantum += n_window_quantum
173 | packed_loads = [max_load, ]
174 | packed_loads.extend(loads[trace_cpuid_low: trace_cpuid_high + 1])
175 | packed_loads.append(has_input_event)
176 | packed_loads_seq.append(packed_loads)
177 |
178 | # 注意:16ms的帧可以横跨三个10ms的窗口
179 | # 帧在第x个ms开始,帧内16ms的在各个核心的负载的最大值
180 | packed_render_loads_seq = []
181 | len_busy_seq = len(busy_seq)
182 | n_frame_quantum = int(frame_sec / quantum_sec)
183 | for render_start_time in render_seq:
184 | idx_start = int(render_start_time / quantum_sec)
185 | idx_end = idx_start + n_frame_quantum
186 | if idx_end > len_busy_seq:
187 | break
188 | period_sum_busy = [0.0] * n_cpu
189 | for idx_busy in range(idx_start, idx_end):
190 | for cpuid in range(trace_cpuid_low, trace_cpuid_high + 1):
191 | period_sum_busy[cpuid] += busy_seq[idx_busy][cpuid]
192 | period_max_load = busy_ratio_to_load(max(period_sum_busy) / frame_sec)
193 | packed_render_loads_seq.append((idx_start, period_max_load))
194 |
195 | return packed_loads_seq, packed_render_loads_seq
196 |
197 |
198 | def merge_packed_seq(packed_loads_seq_arr, packed_render_loads_seq_arr):
199 | merged_loads = list()
200 | merged_renders = list()
201 | idx_quantum_base = 0
202 | for packed_loads_seq, packed_render_loads_seq in zip(packed_loads_seq_arr, packed_render_loads_seq_arr):
203 | merged_loads.extend(packed_loads_seq)
204 | merged_renders.extend( [ (idx_start + idx_quantum_base, period_max_load) for idx_start, period_max_load in packed_render_loads_seq] )
205 | # 由于负载序列生成时,最后不满10ms也就是一个window窗长的负载会被丢弃
206 | # 负载序列在尾部拼接完毕后,根据当前负载序列结束时的quantum(ms)数,来设置下一个渲染需求序列的quantum(ms)的序号偏移
207 | idx_quantum_base += len(packed_loads_seq) * int(window_sec / quantum_sec)
208 | return merged_loads, merged_renders
209 |
210 | def parse_load_set(set_path, out_path, sector_key):
211 | info_filename = 'info.json'
212 | info = None
213 | with open(set_path + info_filename, 'r') as filename:
214 | info = json.load(filename)
215 | sector = info[sector_key]
216 |
217 | if len(sector['loadSeq']):
218 | todos = sector['loadSeq']
219 | else:
220 | print("ERROR: " + sector_key + ".loadSeq is empty")
221 | exit(-1)
222 |
223 | name_arr = list()
224 | packed_loads_seq_arr = list()
225 | packed_render_loads_seq_arr = list()
226 |
227 | for filename in todos:
228 | packed_loads_seq, packed_render_loads_seq = parse_trace(set_path + filename)
229 | name_arr.append(filename)
230 | packed_loads_seq_arr.append(packed_loads_seq)
231 | packed_render_loads_seq_arr.append(packed_render_loads_seq)
232 | packed_data = {
233 | 'src': [filename,],
234 | 'ver': 1,
235 | 'quantumSec': quantum_sec,
236 | 'windowQuantum': int(window_sec / quantum_sec),
237 | 'frameQuantum': int(frame_sec / quantum_sec),
238 | 'efficiencyA53': 1024,
239 | 'efficiency': info['efficiency'],
240 | 'freq': info['freq'],
241 | 'loadScale': load_scale,
242 | 'coreNum': trace_cpuid_high - trace_cpuid_low + 1,
243 | 'windowedLoadLen': len(packed_loads_seq),
244 | 'windowedLoad': packed_loads_seq,
245 | 'renderLoad': packed_render_loads_seq
246 | }
247 | with open(out_path + filename[:-5] + '.json', 'w') as f:
248 | json.dump(packed_data, f, indent=None, separators=(',', ':'))
249 |
250 | if need_merged_file:
251 | merged_loads, merged_renders = merge_packed_seq(packed_loads_seq_arr, packed_render_loads_seq_arr)
252 | packed_data = {
253 | 'src': name_arr,
254 | 'ver': 1,
255 | 'quantumSec': quantum_sec,
256 | 'windowQuantum': int(window_sec / quantum_sec),
257 | 'frameQuantum': int(frame_sec / quantum_sec),
258 | 'efficiencyA53': 1024,
259 | 'efficiency': info['efficiency'],
260 | 'freq': info['freq'],
261 | 'loadScale': load_scale,
262 | 'coreNum': trace_cpuid_high - trace_cpuid_low + 1,
263 | 'windowedLoadLen': len(merged_loads),
264 | 'windowedLoad': merged_loads,
265 | 'renderLoad': merged_renders
266 | }
267 | with open(out_path + sector_key + '-merged' + '.json', 'w') as f:
268 | json.dump(packed_data, f, indent=None, separators=(',', ':'))
269 | return
270 |
271 |
272 | # todos = [
273 | # # raw_path + 'bili-danmu.html',
274 | # 'gflops.html',
275 | # # 'trace.html'
276 | # ]
277 |
278 | parse_load_set(raw_path, out_path, "onscreen")
279 | parse_load_set(raw_path, out_path, "offscreen")
280 | # parse_trace(todos[0])
281 |
--------------------------------------------------------------------------------