Skip to content

Commit 1398292

Browse files
committed
cpuidle: menu: Use one loop for average and variance computations
Use the observation that one loop is sufficient to compute the average of an array of values and their variance to eliminate one of the loops from get_typical_interval(). While at it, make get_typical_interval() consistently use u64 as the 64-bit unsigned integer data type and rearrange some white space and the declarations of local variables in it (to make them follow the reverse X-mas tree pattern). No intentional functional impact. Signed-off-by: Rafael J. Wysocki <[email protected]> Tested-by: Artem Bityutskiy <[email protected]> Reviewed-by: Christian Loehle <[email protected]> Tested-by: Christian Loehle <[email protected]> Tested-by: Aboorva Devarajan <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent d2cd195 commit 1398292

File tree

1 file changed

+28
-33
lines changed
  • drivers/cpuidle/governors

1 file changed

+28
-33
lines changed

drivers/cpuidle/governors/menu.c

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -116,49 +116,45 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
116116
*/
117117
static unsigned int get_typical_interval(struct menu_device *data)
118118
{
119-
int i, divisor;
120-
unsigned int max, thresh, avg;
121-
uint64_t sum, variance;
122-
123-
thresh = INT_MAX; /* Discard outliers above this value */
119+
unsigned int max, divisor, thresh = INT_MAX;
120+
u64 avg, variance, avg_sq;
121+
int i;
124122

125123
again:
126-
127-
/* First calculate the average of past intervals */
124+
/* Compute the average and variance of past intervals. */
128125
max = 0;
129-
sum = 0;
126+
avg = 0;
127+
variance = 0;
130128
divisor = 0;
131129
for (i = 0; i < INTERVALS; i++) {
132130
unsigned int value = data->intervals[i];
133-
if (value <= thresh) {
134-
sum += value;
135-
divisor++;
136-
if (value > max)
137-
max = value;
138-
}
131+
132+
/* Discard data points above the threshold. */
133+
if (value > thresh)
134+
continue;
135+
136+
divisor++;
137+
138+
avg += value;
139+
variance += (u64)value * value;
140+
141+
if (value > max)
142+
max = value;
139143
}
140144

141145
if (!max)
142146
return UINT_MAX;
143147

144-
if (divisor == INTERVALS)
145-
avg = sum >> INTERVAL_SHIFT;
146-
else
147-
avg = div_u64(sum, divisor);
148-
149-
/* Then try to determine variance */
150-
variance = 0;
151-
for (i = 0; i < INTERVALS; i++) {
152-
unsigned int value = data->intervals[i];
153-
if (value <= thresh) {
154-
int64_t diff = (int64_t)value - avg;
155-
variance += diff * diff;
156-
}
157-
}
158-
if (divisor == INTERVALS)
148+
if (divisor == INTERVALS) {
149+
avg >>= INTERVAL_SHIFT;
159150
variance >>= INTERVAL_SHIFT;
160-
else
151+
} else {
152+
do_div(avg, divisor);
161153
do_div(variance, divisor);
154+
}
155+
156+
avg_sq = avg * avg;
157+
variance -= avg_sq;
162158

163159
/*
164160
* The typical interval is obtained when standard deviation is
@@ -173,10 +169,9 @@ static unsigned int get_typical_interval(struct menu_device *data)
173169
* Use this result only if there is no timer to wake us up sooner.
174170
*/
175171
if (likely(variance <= U64_MAX/36)) {
176-
if ((((u64)avg*avg > variance*36) && (divisor * 4 >= INTERVALS * 3))
177-
|| variance <= 400) {
172+
if ((avg_sq > variance * 36 && divisor * 4 >= INTERVALS * 3) ||
173+
variance <= 400)
178174
return avg;
179-
}
180175
}
181176

182177
/*

0 commit comments

Comments
 (0)