Fix maxMemFreq detection; Add some other alternative governor logic

This commit is contained in:
KazushiM
2022-11-01 23:08:23 +08:00
parent 72a8421df6
commit 523d2dc45a
4 changed files with 185 additions and 51 deletions

View File

@@ -5,21 +5,21 @@ CpuCoreUtil::CpuCoreUtil(int coreid = -2, uint64_t ns = 1000'000ULL)
uint32_t CpuCoreUtil::Get() {
struct _ctx {
uint64_t timestamp;
uint64_t systick;
uint64_t idletick;
} begin, end;
begin.timestamp = armTicksToNs(armGetSystemTick());
begin.systick = armGetSystemTick();
begin.idletick = GetIdleTickCount();
svcSleepThread(m_wait_time_ns);
end.timestamp = armTicksToNs(armGetSystemTick());
end.systick = armGetSystemTick();
end.idletick = GetIdleTickCount();
uint64_t diff_idletick = end.idletick - begin.idletick;
uint64_t real_elapsed_ns = end.timestamp - begin.timestamp;
return UTIL_MAX - diff_idletick * 10 * 1000'000ULL / (TICKS_PER_MS * real_elapsed_ns);
uint64_t diff_systick = end.systick - begin.systick;
return UTIL_MAX - diff_idletick * 10 * 100ULL / diff_systick;
}
uint64_t CpuCoreUtil::GetIdleTickCount() {
@@ -209,10 +209,6 @@ void Governor::SetMaxHz(uint32_t max_hz, SysClkModule module) {
m_gpu_freq.max_hz = max_hz;
m_gpu_freq.min_hz = (m_gpu_freq.max_hz <= 153'600'000) ? max_hz : 153'600'000;
break;
case SysClkModule_MEM:
m_mem_freq = max_hz;
Clocks::SetHz(SysClkModule_MEM, max_hz);
break;
default:
break;
}
@@ -234,24 +230,103 @@ uint32_t Governor::s_FreqContext::GetNormalizedUtil(uint32_t raw_util) {
// next_freq = C * max_freq(ref_freq) * util / max
void Governor::s_FreqContext::SetNextFreq(uint32_t norm_util) {
uint32_t prev_hz = target_hz;
uint32_t next_freq = (uint64_t)(norm_util + (norm_util >> 1)) * utilref_hz / UTIL_MAX;
uint32_t adj_next_freq = target_hz;
if (next_freq > max_hz) {
adj_next_freq = max_hz;
} else if (next_freq < min_hz) {
adj_next_freq = min_hz;
} else {
// === Add a non-linear coefficient to tipping-point ===
// float nonlinear_coeff = (float)max_hz / target_hz; // Always non-negative
// #ifdef __aarch64__
// asm ("FSQRT %s0, %s0"
// : "=w" (nonlinear_coeff)
// : "w" (nonlinear_coeff));
// asm ("FSQRT %s0, %s0"
// : "=w" (nonlinear_coeff)
// : "w" (nonlinear_coeff));
// #else
// nonlinear_coeff = sqrt(sqrt(nonlinear_coeff));
// #endif
// === Tipping-point look-up table for all frequencies ===
// typedef struct {
// uint16_t numerator;
// uint16_t denom_shift;
// } lut_entry;
// static constexpr auto apply_cpu_nonlinear_coeff = [](uint32_t input) {
// lut_entry lut[] = {
// { 4645, 12 }, // 1963500000
// {},
// { 4505, 12 }, // 2091000000
// { 8971, 13 }, // 2193000000
// { 1117, 10 }, // 2295000000
// { 1117, 10 }, // 2397000000
// {},
// { 5575, 12 }, // 612000000
// { 10699, 13 }, // 714000000
// {},
// { 81, 6 }, // 816000000
// { 10113, 13 }, // 918000000
// { 1239, 10 }, // 1020000000
// {},
// { 9749, 13 }, // 1122000000
// { 4807, 12 }, // 1224000000
// { 2375, 11 }, // 1326000000
// { 10041, 13 }, // 1428000000
// {},
// { 9283, 13 }, // 1581000000
// {},
// { 9215, 13 }, // 1683000000
// { 18309, 14 }, // 1785000000
// };
// size_t idx = (input >> 20) % 24;
// lut_entry entry = lut[idx];
// return (input >> entry.denom_shift) * entry.numerator;
// };
// static constexpr auto apply_gpu_nonlinear_coeff = [](uint32_t input) {
// lut_entry lut[] = {
// { 1087, 10 }, // 1305600000
// { 2351, 11 }, // 1075200000
// { 9749, 13 }, // 844800000
// { 81, 6 }, // 614400000
// { 2949, 11 }, // 384000000
// { 9, 2 }, // 153600000
// {},
// { 1089, 10 }, // 1228800000
// { 2375, 11 }, // 998400000
// { 1239, 10 }, // 768000000
// { 10699, 13 }, // 537600000
// { 25, 4 }, // 307200000
// { 4, 0 }, // 76800000
// { 1087, 10 }, // 1267200000
// { 1165, 10 }, // 1152000000
// { 4807, 12 }, // 921600000
// { 10113, 13 }, // 691200000
// { 5575, 12 }, // 460800000
// };
// size_t idx = (input >> 18) % 20;
// lut_entry entry = lut[idx];
// return (input >> entry.denom_shift) * entry.numerator;
// };
auto FindHzInTable = [](uint32_t* hz_list, uint32_t in_hz) {
uint32_t* p = hz_list;
do {
if (*p >= next_freq) {
adj_next_freq = *p;
break;
}
} while (*p++);
}
while (*p) {
if (in_hz <= *p)
return p;
p++;
}
return (--p);
};
uint32_t next_freq = utilref_hz / UTIL_MAX * norm_util;
next_freq += next_freq >> 1;
if (next_freq >= max_hz)
target_hz = max_hz;
else if (next_freq <= min_hz)
target_hz = min_hz;
else
target_hz = *FindHzInTable(hz_list, next_freq);
target_hz = adj_next_freq;
bool changed = target_hz != prev_hz;
if (changed)
SetHz();
@@ -262,7 +337,7 @@ void Governor::s_FreqContext::SetHz() {
Clocks::SetHz(module, target_hz);
}
void Governor::s_FreqContext::SetBoostHz() {
void Governor::s_FreqContext::Boost() {
target_hz = boost_hz;
if (module == SysClkModule_CPU && max_hz > boost_hz)
target_hz = max_hz;
@@ -275,9 +350,7 @@ void Governor::CpuUtilWorker(void* args) {
Governor* self = s->self;
while (self->m_running) {
uint64_t timestamp = armTicksToNs(armGetSystemTick());
s->timestamp = timestamp;
uint64_t tick = s->tick = armGetSystemTick();
s->util = self->m_cpu_freq.GetNormalizedUtil(CpuCoreUtil(coreid, TICK_TIME_NS).Get());
bool CPUBoosted = apmExtIsCPUBoosted(self->m_perf_conf_id);
@@ -287,11 +360,15 @@ void Governor::CpuUtilWorker(void* args) {
}
for (int id = 0; id < CORE_NUMS; id++) {
if (abs(self->m_cpu_core_ctx[id].timestamp - timestamp) < TICK_TIME_NS * 10)
if (id == coreid)
continue;
uint64_t diff = std::abs((int64_t)self->m_cpu_core_ctx[id].tick - (int64_t)tick);
if (diff < SYSTICK_HZ / SAMPLE_RATE * 10)
continue;
if (id == SYS_CORE_ID && self->m_syscore_autoboost) {
self->m_cpu_freq.SetBoostHz();
self->m_cpu_freq.Boost();
break;
}
@@ -316,8 +393,8 @@ void Governor::Main(void* args) {
util = self->m_cpu_core_ctx[i].util;
}
cpu_util.Update(util);
if (self->m_cpu_core_ctx[SYS_CORE_ID].util > 95'0 && self->m_syscore_autoboost)
cpu_ctx->SetBoostHz();
if (self->m_cpu_core_ctx[SYS_CORE_ID].util > BOOST_THRESHOLD && self->m_syscore_autoboost)
cpu_ctx->Boost();
else
cpu_ctx->SetNextFreq(cpu_util.Get());
};
@@ -350,18 +427,12 @@ void Governor::Main(void* args) {
gpu_ctx->target_hz = hz;
if (GPUThrottled)
gpu_ctx->SetBoostHz();
gpu_ctx->Boost();
hz = Clocks::GetCurrentHz(SysClkModule_CPU);
cpu_ctx->target_hz = hz;
if (CPUBoosted)
cpu_ctx->SetBoostHz();
hz = Clocks::GetCurrentHz(SysClkModule_MEM);
if (!self->m_mem_freq)
self->m_mem_freq = hz;
if (hz != self->m_mem_freq)
Clocks::SetHz(SysClkModule_MEM, self->m_mem_freq);
cpu_ctx->Boost();
}
if (!GPUThrottled)