From: David Hunt Date: Wed, 24 Jul 2019 13:18:03 +0000 (+0100) Subject: examples/vm_power: fix OOB frequency oscillations X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=31c9a66465ad623258c4449fea54c0b42a2deae1;p=dpdk.git examples/vm_power: fix OOB frequency oscillations The branch ratio algorithm in the vm_power_manager sample application can be very sensitive at patricular loads in a workload, causing oscillations between min and max frequency. For example, if a workload is at 50%, scaling up may change the ratio enough that it immediately thinks it needs to scale down again. This patch introduces a sliding window recording the scale up/down direction for the last 32 samples, and scales up if any samples indicate we should scale up, otherwise scale down. Each core has it's own window. Fixes: 4b1a631b8a8a ("examples/vm_power: add oob monitoring functions") Cc: stable@dpdk.org Signed-off-by: David Hunt Acked-by: Anatoly Burakov --- diff --git a/examples/vm_power_manager/oob_monitor_x86.c b/examples/vm_power_manager/oob_monitor_x86.c index ebd96b205f..aecfcb2ebf 100644 --- a/examples/vm_power_manager/oob_monitor_x86.c +++ b/examples/vm_power_manager/oob_monitor_x86.c @@ -39,6 +39,7 @@ apply_policy(int core) int64_t hits_diff, miss_diff; float ratio; int ret; + int freq_window_idx, up_count = 0, i; g_active = 0; ci = get_core_info(); @@ -101,10 +102,37 @@ apply_policy(int core) ratio = (float)miss_diff * (float)100 / (float)hits_diff; - if (ratio < ci->branch_ratio_threshold) - power_manager_scale_core_min(core); + /* + * Store the last few directions that the ratio indicates + * we should take. If there's on 'up', then we scale up + * quickly. If all indicate 'down', only then do we scale + * down. Each core_details struct has it's own array. + */ + freq_window_idx = ci->cd[core].freq_window_idx; + if (ratio > ci->branch_ratio_threshold) + ci->cd[core].freq_directions[freq_window_idx] = 1; else - power_manager_scale_core_max(core); + ci->cd[core].freq_directions[freq_window_idx] = 0; + + freq_window_idx++; + freq_window_idx = freq_window_idx & (FREQ_WINDOW_SIZE-1); + ci->cd[core].freq_window_idx = freq_window_idx; + + up_count = 0; + for (i = 0; i < FREQ_WINDOW_SIZE; i++) + up_count += ci->cd[core].freq_directions[i]; + + if (up_count == 0) { + if (ci->cd[core].freq_state != FREQ_MIN) { + power_manager_scale_core_min(core); + ci->cd[core].freq_state = FREQ_MIN; + } + } else { + if (ci->cd[core].freq_state != FREQ_MAX) { + power_manager_scale_core_max(core); + ci->cd[core].freq_state = FREQ_MAX; + } + } g_active = 1; return ratio; diff --git a/examples/vm_power_manager/power_manager.c b/examples/vm_power_manager/power_manager.c index 9d4e587b0f..7b4f4b3c4d 100644 --- a/examples/vm_power_manager/power_manager.c +++ b/examples/vm_power_manager/power_manager.c @@ -62,14 +62,13 @@ core_info_init(void) ci->core_count = get_nprocs_conf(); ci->branch_ratio_threshold = BRANCH_RATIO_THRESHOLD; ci->cd = malloc(ci->core_count * sizeof(struct core_details)); + memset(ci->cd, 0, ci->core_count * sizeof(struct core_details)); if (!ci->cd) { RTE_LOG(ERR, POWER_MANAGER, "Failed to allocate memory for core info."); return -1; } for (i = 0; i < ci->core_count; i++) { ci->cd[i].global_enabled_cpus = 1; - ci->cd[i].oob_enabled = 0; - ci->cd[i].msr_fd = 0; } printf("%d cores in system\n", ci->core_count); return 0; diff --git a/examples/vm_power_manager/power_manager.h b/examples/vm_power_manager/power_manager.h index e81a60ae54..e324766b6f 100644 --- a/examples/vm_power_manager/power_manager.h +++ b/examples/vm_power_manager/power_manager.h @@ -8,12 +8,24 @@ #ifdef __cplusplus extern "C" { #endif + +#define FREQ_WINDOW_SIZE 32 + +enum { + FREQ_UNKNOWN, + FREQ_MIN, + FREQ_MAX +}; + struct core_details { uint64_t last_branches; uint64_t last_branch_misses; uint16_t global_enabled_cpus; uint16_t oob_enabled; int msr_fd; + uint16_t freq_directions[FREQ_WINDOW_SIZE]; + uint16_t freq_window_idx; + uint16_t freq_state; }; struct core_info {