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 <david.hunt@intel.com> Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>
This commit is contained in:
parent
eccc5d3237
commit
31c9a66465
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user