Skip to contentSkip to conversation

cpufreq: ondemand: Calculate gradient of CPU load to early increase frequency

PATCH In review Stratos Karafotis 3 participants 13 messages Feb 20, 2013 – Apr 2, 2013 CPU frequency scaling framework

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 cpufreq: ondemand: Calculate gradient of CPU load to early increase frequency

Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s). We reduce up_threshold by early_differential to achieve frequency increase in the current iteration.

A new tuner early_demand is introduced to enable this functionality (disabled by default). Also we use new tuners to control early demand:

- early_differential: controls the final up_threshold
- grad_up_threshold: over this gradient of load we will decrease up_threshold by early_differential.

---
 drivers/cpufreq/cpufreq_governor.c |  1 +
 drivers/cpufreq/cpufreq_governor.h |  4 ++++
 drivers/cpufreq/cpufreq_ondemand.c | 41 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 45 insertions(+), 1 deletion(-)
drivers/cpufreq/cpufreq_governor.c +1 -0
index 5a76086..348cb80 100644
@@ -276,6 +276,7 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
 		} else {
 			od_dbs_info->rate_mult = 1;
 			od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+			od_dbs_info->prev_load_freq = 0;
 			od_ops->powersave_bias_init_cpu(cpu);
 
 			if (!policy->governor->initialized)
drivers/cpufreq/cpufreq_governor.h +4 -0
index d2ac911..d1425a7 100644
@@ -94,6 +94,7 @@ struct od_cpu_dbs_info_s {
 	unsigned int freq_hi_jiffies;
 	unsigned int rate_mult;
 	unsigned int sample_type:1;
+	unsigned int prev_load_freq;
 };
 
 struct cs_cpu_dbs_info_s {
@@ -112,6 +113,9 @@ struct od_dbs_tuners {
 	unsigned int adj_up_threshold;
 	unsigned int powersave_bias;
 	unsigned int io_is_busy;
+	unsigned int early_differential;
+	unsigned int grad_up_threshold;
+	unsigned int early_demand;
 };
 
 struct cs_dbs_tuners {
drivers/cpufreq/cpufreq_ondemand.c +40 -1

89 lines not on this page · raw message

Signature · 1 line
1.8.1.2
maintainer
#1 lore raw

Hi Stratos,

Quoted 10 lines · Stratos Karafotis

Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s). We reduce up_threshold by early_differential to achieve frequency increase in the current iteration.

Quoted 8 lines

A new tuner early_demand is introduced to enable this functionality (disabled by default). Also we use new tuners to control early demand:

- early_differential: controls the final up_threshold
- grad_up_threshold: over this gradient of load we will decrease up_threshold by early_differential.

Sorry for this but i already have a patchset which has changed these files to some extent. Can you please rebase over them? Actually my patchset is already accepted, its just that rafael didn't wanted to have them for 3.9.

http://git.linaro.org/gitweb?p=people/vireshk/linux.git;a=shortlog;h=refs/heads/cpufreq-for-3.10

Back to your patch:

Following is what i understood about this patch:
- The only case where this code will come into picture is when load is below up_threshold.
- And we see a steep rise in the load from previous request..

i.e. (with the default values)

UP_THRESHOLD (80)
GRAD_UP_THESHOLD (50)
EARLY_DIFFERENTIAL (45)

If the load was 10 previously and it went to 80 > load >= 60, we will make up_threshold as 80-45 = 35. Which is lower than grad_up_threshold :)

Isn't it strange?

So, probably you just don't need this tunable: early_differential. Rather just increase the frequency without doing this calculation:

if (load_freq > od_tuners.up_threshold * policy->cur) {

drivers/cpufreq/cpufreq_ondemand.c line 33

Quoted 9 lines
drivers/cpufreq/cpufreq_ondemand.c +1 -0
index f3eb26c..458806f 100644
@@ -30,6 +30,8 @@
 #define DEF_FREQUENCY_DOWN_DIFFERENTIAL                (10)
 #define DEF_FREQUENCY_UP_THRESHOLD             (80)
 #define DEF_SAMPLING_DOWN_FACTOR               (1)
+#define DEF_GRAD_UP_THESHOLD                   (50)

s/THESHOLD/THRESHOLD

Quoted 7 lines
drivers/cpufreq/cpufreq_ondemand.c +2 -0
@@ -170,11 +175,29 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
 {
        struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
        struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+       unsigned int up_threshold = od_tuners.up_threshold;
+       unsigned int grad;
 

drivers/cpufreq/cpufreq_ondemand.c static void od_check_cpu(int cpu, unsigned int load_freq) · line 190

Quoted 10 lines
drivers/cpufreq/cpufreq_ondemand.c +8 -0
        dbs_info->freq_lo = 0;
 
+       /*
+        * Calculate the gradient of load_freq. If it is too steep we assume
+        * that the load will go over up_threshold in next iteration(s). We
+        * reduce up_threshold by early_differential to achieve frequency
+        * increase earlier
+        */
+       if (od_tuners.early_demand) {
+               if (load_freq > dbs_info->prev_load_freq) {

&& (load_freq < od_tuners.up_threshold * policy->cur) ??

Quoted 15 lines
drivers/cpufreq/cpufreq_ondemand.c +9 -1
+                       grad = load_freq - dbs_info->prev_load_freq;
+
+                       if (grad > od_tuners.grad_up_threshold * policy->cur)
+                               up_threshold -= od_tuners.early_differential;
+               }
+               dbs_info->prev_load_freq = load_freq;
+       }
+
        /* Check for frequency increase */
-       if (load_freq > od_tuners.up_threshold * policy->cur) {
+       if (load_freq > up_threshold * policy->cur) {
                /* If switching to max speed, apply sampling_down_factor */
                if (policy->cur < policy->max)
                        dbs_info->rate_mult =

drivers/cpufreq/cpufreq_ondemand.c static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, · line 464

Quoted 4 lines
drivers/cpufreq/cpufreq_ondemand.c +1 -0
@@ -438,12 +461,26 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
        return count;
 }
 
+show_one(od, early_demand, early_demand);

What about making other two tunables rw?

#2 lore raw

Hi Viresh,

Thank you very much for your review and your suggestions.

Quoted 5 lines · Viresh Kumar

Sorry for this but i already have a patchset which has changed these files to some extent. Can you please rebase over them? Actually my patchset is already accepted, its just that rafael didn't wanted to have them for 3.9.

http://git.linaro.org/gitweb?p=people/vireshk/linux.git;a=shortlog;h=refs/heads/cpufreq-for-3.10

No problem. I rebased the patch over your tree.

Quoted 4 lines

So, probably you just don't need this tunable: early_differential. Rather just increase the frequency without doing this calculation:

if (load_freq > od_tuners.up_threshold * policy->cur) {

I agree with your suggestion. This is simpler approach. So, if the gradient is greater than grad_up_threshold we increase frequency immediately. i.e.

if previous load was 10 and current load is 65 the gradient will be 55 (> grad_up_theshold) and we increase frequency

Quoted 4 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+       if (od_tuners.early_demand) {
+               if (load_freq > dbs_info->prev_load_freq) {

&& (load_freq < od_tuners.up_threshold * policy->cur) ??

In my opinion this is not necessary. If load_freq is greater, then we have to increase frequency in anyway.

Quoted 5 lines
Quoted 2 lines

+show_one(od, early_demand, early_demand);

What about making other two tunables rw?

Of course. I added the grad_up_threshold.

Following patch v2.

Thanks again,
Stratos

------------------------8<---------------------------------------------- Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s) and we increase frequency immediately.

New tuners are introduced:
- early_demand: to enable this functionality (disabled by default).
- grad_up_threshold: over this gradient of load we will increase frequency immediately.

---
 drivers/cpufreq/cpufreq_governor.c |  1 +
 drivers/cpufreq/cpufreq_governor.h |  6 +++-
 drivers/cpufreq/cpufreq_ondemand.c | 72 ++++++++++++++++++++++++++++++++++----
 3 files changed, 72 insertions(+), 7 deletions(-)
drivers/cpufreq/cpufreq_governor.c +1 -0
index 7722505..e737aa9 100644
@@ -322,6 +322,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		} else {
 			od_dbs_info->rate_mult = 1;
 			od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+			od_dbs_info->prev_load_freq = 0;
 			od_ops->powersave_bias_init_cpu(cpu);
 		}
 
drivers/cpufreq/cpufreq_governor.h +5 -1
index 6301790..c9a237a 100644
@@ -96,6 +96,7 @@ struct od_cpu_dbs_info_s {
 	unsigned int freq_hi_jiffies;
 	unsigned int rate_mult;
 	unsigned int sample_type:1;
+	unsigned int prev_load_freq;
 };
 
 struct cs_cpu_dbs_info_s {
@@ -114,6 +115,8 @@ struct od_dbs_tuners {
 	unsigned int adj_up_threshold;
 	unsigned int powersave_bias;
 	unsigned int io_is_busy;
+	unsigned int grad_up_threshold;
+	unsigned int early_demand;
 };
 
 struct cs_dbs_tuners {
@@ -160,7 +163,8 @@ struct od_ops {
 	void (*powersave_bias_init_cpu)(int cpu);
 	unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
 			unsigned int freq_next, unsigned int relation);
-	void (*freq_increase)(struct cpufreq_policy *p, unsigned int freq);
+	void (*freq_increase)(struct od_cpu_dbs_info_s *dbs_info,
+			      struct cpufreq_policy *p, unsigned int freq);
 };
 
 struct cs_ops {
drivers/cpufreq/cpufreq_ondemand.c +66 -6

132 lines not on this page · raw message

Signature · 1 line
1.8.1.2
maintainer
#3 lore raw

Hi Again,

Quoted 25 lines · Stratos Karafotis
drivers/cpufreq/cpufreq_ondemand.c +17 -0
@@ -168,16 +174,29 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
        struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
        struct dbs_data *dbs_data = policy->governor_data;
        struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+       unsigned int prev_load_freq;
 
        dbs_info->freq_lo = 0;
 
+       /*
+        * Calculate the gradient of load_freq. If it is too steep we assume
+        * that the load will go over up_threshold in next iteration(s) and
+        * we increase the frequency immediately
+        */
+       if (od_tuners->early_demand) {
+               prev_load_freq = dbs_info->prev_load_freq;
+               dbs_info->prev_load_freq = load_freq;
+
+               if (load_freq > prev_load_freq && (load_freq - prev_load_freq >
+                   od_tuners->grad_up_threshold * policy->cur)) {
+                       dbs_freq_increase(dbs_info, policy, policy->max);
+                       return;
+               }
+       }
+

drivers/cpufreq/cpufreq_ondemand.c static void od_check_cpu(int cpu, unsigned int load_freq) · line 201

Quoted 10 lines
drivers/cpufreq/cpufreq_ondemand.c +1 -5
        /* Check for frequency increase */
        if (load_freq > od_tuners->up_threshold * policy->cur) {
-               /* If switching to max speed, apply sampling_down_factor */
-               if (policy->cur < policy->max)
-                       dbs_info->rate_mult =
-                               od_tuners->sampling_down_factor;
-               dbs_freq_increase(policy, policy->max);
+               dbs_freq_increase(dbs_info, policy, policy->max);
                return;
        }

Not really against your implementation, but this is what i thought of how it should look like (initially when i reviewed your V1)

int boost_freq = 0;

       if (od_tuners->early_demand) {
               if (load_freq > dbs_info->prev_load_freq && (load_freq
- dbs_info->prev_load_freq >
                   od_tuners->grad_up_threshold * policy->cur)) {
                   boost_freq = 1;
               }

               dbs_info->prev_load_freq = load_freq;
       }

        /* Check for frequency increase */
        if (boost_freq || (load_freq > od_tuners->up_threshold * policy->cur)) {
                 increase-freq;

This would get rid of duplicate calls to increase_freq() and also avoid changing its
prototype.

#4 lore raw

Hi,

Quoted 19 lines · Viresh Kumar

Hi Again,

int boost_freq = 0;

        if (od_tuners->early_demand) {
                if (load_freq > dbs_info->prev_load_freq && (load_freq
- dbs_info->prev_load_freq >
                    od_tuners->grad_up_threshold * policy->cur)) {
                    boost_freq = 1;
                }

                dbs_info->prev_load_freq = load_freq;
        }

         /* Check for frequency increase */
         if (boost_freq || (load_freq > od_tuners->up_threshold * policy->cur)) {
                  increase-freq;
Quoted 4 lines

This would get rid of duplicate calls to increase_freq() and also avoid changing its
prototype.

Thanks again. Following V3 with your suggestion.

Regards,
Stratos

-----------------------8<-------------------------------------------- Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s) and we increase frequency immediately.

New tuners are introduced:
- early_demand: to enable this functionality (disabled by default).
- grad_up_threshold: over this gradient of load we will increase frequency immediately.

---
 drivers/cpufreq/cpufreq_governor.c |  1 +
 drivers/cpufreq/cpufreq_governor.h |  3 ++
 drivers/cpufreq/cpufreq_ondemand.c | 59 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 62 insertions(+), 1 deletion(-)
drivers/cpufreq/cpufreq_governor.c +1 -0
index 7722505..e737aa9 100644
@@ -322,6 +322,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		} else {
 			od_dbs_info->rate_mult = 1;
 			od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+			od_dbs_info->prev_load_freq = 0;
 			od_ops->powersave_bias_init_cpu(cpu);
 		}
 
drivers/cpufreq/cpufreq_governor.h +3 -0
index 6301790..3a703b9 100644
@@ -96,6 +96,7 @@ struct od_cpu_dbs_info_s {
 	unsigned int freq_hi_jiffies;
 	unsigned int rate_mult;
 	unsigned int sample_type:1;
+	unsigned int prev_load_freq;
 };
 
 struct cs_cpu_dbs_info_s {
@@ -114,6 +115,8 @@ struct od_dbs_tuners {
 	unsigned int adj_up_threshold;
 	unsigned int powersave_bias;
 	unsigned int io_is_busy;
+	unsigned int grad_up_threshold;
+	unsigned int early_demand;
 };
 
 struct cs_dbs_tuners {
drivers/cpufreq/cpufreq_ondemand.c +58 -1

108 lines not on this page · raw message

Signature · 1 line
1.8.1.2
maintainer Acked-by
#5 lore raw
Quoted 14 lines · Stratos Karafotis

Thanks again. Following V3 with your suggestion.

Regards,
Stratos

-----------------------8<-------------------------------------------- Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s) and we increase frequency immediately.

Quoted 6 lines

New tuners are introduced:
- early_demand: to enable this functionality (disabled by default).
- grad_up_threshold: over this gradient of load we will increase frequency immediately.

maintainer
#6 lore raw
Quoted 10 lines · Viresh Kumar
Quoted 8 lines · Stratos Karafotis

Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s) and we increase frequency immediately.

Quoted 8 lines
Quoted 6 lines

New tuners are introduced:
- early_demand: to enable this functionality (disabled by default).
- grad_up_threshold: over this gradient of load we will increase frequency immediately.

Rafael,

I applied it here with my Ack over my patches, for getting a run by "kbuild test robot".

http://git.linaro.org/gitweb?p=people/vireshk/linux.git;a=shortlog;h=refs/heads/cpufreq-for-3.10

#7 lore raw
Quoted 18 lines · Viresh Kumar
Quoted 17 lines · Viresh Kumar
Quoted 14 lines · Stratos Karafotis

Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s) and we increase frequency immediately.

New tuners are introduced:
- early_demand: to enable this functionality (disabled by default).
- grad_up_threshold: over this gradient of load we will increase frequency immediately.

Quoted 8 lines
Quoted 1 line

Rafael,

I applied it here with my Ack over my patches, for getting a run by "kbuild test robot".

http://git.linaro.org/gitweb?p=people/vireshk/linux.git;a=shortlog;h=refs/heads/cpufreq-for-3.10

Thanks, but I'm still not entirely sure about the have_multiple_policies stuff (yes, I saw your arguments) and the v3.10 merge window is still two months away. IOW, please slow down a bit.

Thanks,
Rafael

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#8 lore raw
In reply to Viresh Kumar
Quoted 6 lines · Viresh Kumar
Quoted 1 line · Stratos Karafotis

Hi Rafael,

In case you are interested in this patch I rebased it to the latest linux-pm/bleeding-edge.

Thanks,
Stratos

------------------------------------------
Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s) and we increase frequency immediately.

New tuners are introduced:
- early_demand: to enable this functionality (disabled by default).
- grad_up_threshold: over this gradient of load we will increase frequency immediately.

---
 drivers/cpufreq/cpufreq_governor.c |  1 +
 drivers/cpufreq/cpufreq_governor.h |  3 ++
 drivers/cpufreq/cpufreq_ondemand.c | 59 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 62 insertions(+), 1 deletion(-)
drivers/cpufreq/cpufreq_governor.c +1 -0
index 41e5e56..1d9abc4 100644
@@ -328,6 +328,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		} else {
 			od_dbs_info->rate_mult = 1;
 			od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+			od_dbs_info->prev_load_freq = 0;
 			od_ops->powersave_bias_init_cpu(cpu);
 		}
 
drivers/cpufreq/cpufreq_governor.h +3 -0
index 1f7de13..c33b37a 100644
@@ -95,6 +95,7 @@ struct od_cpu_dbs_info_s {
 	unsigned int freq_hi_jiffies;
 	unsigned int rate_mult;
 	unsigned int sample_type:1;
+	unsigned int prev_load_freq;
 };
 
 struct cs_cpu_dbs_info_s {
@@ -113,6 +114,8 @@ struct od_dbs_tuners {
 	unsigned int adj_up_threshold;
 	unsigned int powersave_bias;
 	unsigned int io_is_busy;
+	unsigned int grad_up_threshold;
+	unsigned int early_demand;
 };
 
 struct cs_dbs_tuners {
drivers/cpufreq/cpufreq_ondemand.c +58 -1

108 lines not on this page · raw message

Signature · 1 line
1.8.1.4
#9 lore raw
Quoted 11 lines · Stratos Karafotis
Quoted 6 lines · Viresh Kumar
Quoted 1 line · Stratos Karafotis

Hi Rafael,

In case you are interested in this patch I rebased it to the latest linux-pm/bleeding-edge.

Thanks!

I have a backlog of cpufreq patches to sort out, so it may take some time till I get to this one.

Thanks,
Rafael

Quoted 173 lines

------------------------------------------
Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s) and we increase frequency immediately.

New tuners are introduced:
- early_demand: to enable this functionality (disabled by default).
- grad_up_threshold: over this gradient of load we will increase frequency immediately.

---
 drivers/cpufreq/cpufreq_governor.c |  1 +
 drivers/cpufreq/cpufreq_governor.h |  3 ++
 drivers/cpufreq/cpufreq_ondemand.c | 59 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 62 insertions(+), 1 deletion(-)
drivers/cpufreq/cpufreq_governor.c +1 -0
index 41e5e56..1d9abc4 100644
@@ -328,6 +328,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		} else {
 			od_dbs_info->rate_mult = 1;
 			od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+			od_dbs_info->prev_load_freq = 0;
 			od_ops->powersave_bias_init_cpu(cpu);
 		}
 
drivers/cpufreq/cpufreq_governor.h +3 -0
index 1f7de13..c33b37a 100644
@@ -95,6 +95,7 @@ struct od_cpu_dbs_info_s {
 	unsigned int freq_hi_jiffies;
 	unsigned int rate_mult;
 	unsigned int sample_type:1;
+	unsigned int prev_load_freq;
 };
 
 struct cs_cpu_dbs_info_s {
@@ -113,6 +114,8 @@ struct od_dbs_tuners {
 	unsigned int adj_up_threshold;
 	unsigned int powersave_bias;
 	unsigned int io_is_busy;
+	unsigned int grad_up_threshold;
+	unsigned int early_demand;
 };
 
 struct cs_dbs_tuners {
drivers/cpufreq/cpufreq_ondemand.c +58 -1
index 29ed48a..6cd59a7 100644
@@ -31,6 +31,7 @@
 #define DEF_FREQUENCY_DOWN_DIFFERENTIAL		(10)
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
+#define DEF_GRAD_UP_THRESHOLD			(50)
 #define MAX_SAMPLING_DOWN_FACTOR		(100000)
 #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL	(3)
 #define MICRO_FREQUENCY_UP_THRESHOLD		(95)
@@ -168,11 +169,26 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
 	struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
 	struct dbs_data *dbs_data = policy->governor_data;
 	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	int boost_freq = 0;
 
 	dbs_info->freq_lo = 0;
 
+	/*
+	 * Calculate the gradient of load_freq. If it is too steep we assume
+	 * that the load will go over up_threshold in next iteration(s) and
+	 * we increase the frequency immediately
+	 */
+	if (od_tuners->early_demand) {
+		if (load_freq > dbs_info->prev_load_freq &&
+		   (load_freq - dbs_info->prev_load_freq >
+		    od_tuners->grad_up_threshold * policy->cur))
+			boost_freq = 1;
+
+		dbs_info->prev_load_freq = load_freq;
+	}
+
 	/* Check for frequency increase */
-	if (load_freq > od_tuners->up_threshold * policy->cur) {
+	if (boost_freq || load_freq > od_tuners->up_threshold * policy->cur) {
 		/* If switching to max speed, apply sampling_down_factor */
 		if (policy->cur < policy->max)
 			dbs_info->rate_mult =
@@ -454,12 +470,47 @@ static ssize_t store_powersave_bias(struct cpufreq_policy *policy,
 	return count;
 }
 
+static ssize_t store_grad_up_threshold(struct cpufreq_policy *policy,
+		const char *buf, size_t count)
+{
+	struct dbs_data *dbs_data = policy->governor_data;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	unsigned int input;
+	int ret;
+	ret = sscanf(buf, "%u", &input);
+
+	if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
+			input < MIN_FREQUENCY_UP_THRESHOLD) {
+		return -EINVAL;
+	}
+
+	od_tuners->grad_up_threshold = input;
+	return count;
+}
+
+static ssize_t store_early_demand(struct cpufreq_policy *policy,
+		const char *buf, size_t count)
+{
+	struct dbs_data *dbs_data = policy->governor_data;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	unsigned int input;
+	int ret;
+
+	ret = sscanf(buf, "%u", &input);
+	if (ret != 1)
+		return -EINVAL;
+	od_tuners->early_demand = !!input;
+	return count;
+}
+
 show_one(od, sampling_rate, sampling_rate);
 show_one(od, io_is_busy, io_is_busy);
 show_one(od, up_threshold, up_threshold);
 show_one(od, sampling_down_factor, sampling_down_factor);
 show_one(od, ignore_nice, ignore_nice);
 show_one(od, powersave_bias, powersave_bias);
+show_one(od, grad_up_threshold, grad_up_threshold);
+show_one(od, early_demand, early_demand);
 declare_show_sampling_rate_min();
 
 cpufreq_freq_attr_rw(sampling_rate);
@@ -468,6 +519,8 @@ cpufreq_freq_attr_rw(up_threshold);
 cpufreq_freq_attr_rw(sampling_down_factor);
 cpufreq_freq_attr_rw(ignore_nice);
 cpufreq_freq_attr_rw(powersave_bias);
+cpufreq_freq_attr_rw(grad_up_threshold);
+cpufreq_freq_attr_rw(early_demand);
 cpufreq_freq_attr_ro(sampling_rate_min);
 
 static struct attribute *dbs_attributes[] = {
@@ -478,6 +531,8 @@ static struct attribute *dbs_attributes[] = {
 	&ignore_nice.attr,
 	&powersave_bias.attr,
 	&io_is_busy.attr,
+	&grad_up_threshold.attr,
+	&early_demand.attr,
 	NULL
 };
 
@@ -525,9 +580,11 @@ static int od_init(struct dbs_data *dbs_data)
 	}
 
 	tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
+	tuners->grad_up_threshold = DEF_GRAD_UP_THRESHOLD;
 	tuners->ignore_nice = 0;
 	tuners->powersave_bias = 0;
 	tuners->io_is_busy = should_io_be_busy();
+	tuners->early_demand = 0;
 
 	dbs_data->tuners = tuners;
 	mutex_init(&dbs_data->mutex);
Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#10 lore raw
In reply to Stratos Karafotis
Quoted 20 lines · Stratos Karafotis
Quoted 6 lines · Viresh Kumar
Quoted 1 line · Stratos Karafotis

Hi Rafael,

In case you are interested in this patch I rebased it to the latest linux-pm/bleeding-edge.

Thanks,
Stratos

------------------------------------------
Instead of checking only the absolute value of CPU load_freq to increase frequency, we detect forthcoming CPU load rise and increase frequency earlier.

Quoted 8 lines

Every sampling rate, we calculate the gradient of load_freq. If it is too steep we assume that the load most probably will go over up_threshold in next iteration(s) and we increase frequency immediately.

New tuners are introduced:
- early_demand: to enable this functionality (disabled by default).
- grad_up_threshold: over this gradient of load we will increase frequency immediately.

Do you have any numbers indicating that this actually makes things better?

Rafael

Quoted 159 lines
---
 drivers/cpufreq/cpufreq_governor.c |  1 +
 drivers/cpufreq/cpufreq_governor.h |  3 ++
 drivers/cpufreq/cpufreq_ondemand.c | 59 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 62 insertions(+), 1 deletion(-)
drivers/cpufreq/cpufreq_governor.c +1 -0
index 41e5e56..1d9abc4 100644
@@ -328,6 +328,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		} else {
 			od_dbs_info->rate_mult = 1;
 			od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+			od_dbs_info->prev_load_freq = 0;
 			od_ops->powersave_bias_init_cpu(cpu);
 		}
 
drivers/cpufreq/cpufreq_governor.h +3 -0
index 1f7de13..c33b37a 100644
@@ -95,6 +95,7 @@ struct od_cpu_dbs_info_s {
 	unsigned int freq_hi_jiffies;
 	unsigned int rate_mult;
 	unsigned int sample_type:1;
+	unsigned int prev_load_freq;
 };
 
 struct cs_cpu_dbs_info_s {
@@ -113,6 +114,8 @@ struct od_dbs_tuners {
 	unsigned int adj_up_threshold;
 	unsigned int powersave_bias;
 	unsigned int io_is_busy;
+	unsigned int grad_up_threshold;
+	unsigned int early_demand;
 };
 
 struct cs_dbs_tuners {
drivers/cpufreq/cpufreq_ondemand.c +58 -1
index 29ed48a..6cd59a7 100644
@@ -31,6 +31,7 @@
 #define DEF_FREQUENCY_DOWN_DIFFERENTIAL		(10)
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
+#define DEF_GRAD_UP_THRESHOLD			(50)
 #define MAX_SAMPLING_DOWN_FACTOR		(100000)
 #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL	(3)
 #define MICRO_FREQUENCY_UP_THRESHOLD		(95)
@@ -168,11 +169,26 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
 	struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
 	struct dbs_data *dbs_data = policy->governor_data;
 	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	int boost_freq = 0;
 
 	dbs_info->freq_lo = 0;
 
+	/*
+	 * Calculate the gradient of load_freq. If it is too steep we assume
+	 * that the load will go over up_threshold in next iteration(s) and
+	 * we increase the frequency immediately
+	 */
+	if (od_tuners->early_demand) {
+		if (load_freq > dbs_info->prev_load_freq &&
+		   (load_freq - dbs_info->prev_load_freq >
+		    od_tuners->grad_up_threshold * policy->cur))
+			boost_freq = 1;
+
+		dbs_info->prev_load_freq = load_freq;
+	}
+
 	/* Check for frequency increase */
-	if (load_freq > od_tuners->up_threshold * policy->cur) {
+	if (boost_freq || load_freq > od_tuners->up_threshold * policy->cur) {
 		/* If switching to max speed, apply sampling_down_factor */
 		if (policy->cur < policy->max)
 			dbs_info->rate_mult =
@@ -454,12 +470,47 @@ static ssize_t store_powersave_bias(struct cpufreq_policy *policy,
 	return count;
 }
 
+static ssize_t store_grad_up_threshold(struct cpufreq_policy *policy,
+		const char *buf, size_t count)
+{
+	struct dbs_data *dbs_data = policy->governor_data;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	unsigned int input;
+	int ret;
+	ret = sscanf(buf, "%u", &input);
+
+	if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
+			input < MIN_FREQUENCY_UP_THRESHOLD) {
+		return -EINVAL;
+	}
+
+	od_tuners->grad_up_threshold = input;
+	return count;
+}
+
+static ssize_t store_early_demand(struct cpufreq_policy *policy,
+		const char *buf, size_t count)
+{
+	struct dbs_data *dbs_data = policy->governor_data;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	unsigned int input;
+	int ret;
+
+	ret = sscanf(buf, "%u", &input);
+	if (ret != 1)
+		return -EINVAL;
+	od_tuners->early_demand = !!input;
+	return count;
+}
+
 show_one(od, sampling_rate, sampling_rate);
 show_one(od, io_is_busy, io_is_busy);
 show_one(od, up_threshold, up_threshold);
 show_one(od, sampling_down_factor, sampling_down_factor);
 show_one(od, ignore_nice, ignore_nice);
 show_one(od, powersave_bias, powersave_bias);
+show_one(od, grad_up_threshold, grad_up_threshold);
+show_one(od, early_demand, early_demand);
 declare_show_sampling_rate_min();
 
 cpufreq_freq_attr_rw(sampling_rate);
@@ -468,6 +519,8 @@ cpufreq_freq_attr_rw(up_threshold);
 cpufreq_freq_attr_rw(sampling_down_factor);
 cpufreq_freq_attr_rw(ignore_nice);
 cpufreq_freq_attr_rw(powersave_bias);
+cpufreq_freq_attr_rw(grad_up_threshold);
+cpufreq_freq_attr_rw(early_demand);
 cpufreq_freq_attr_ro(sampling_rate_min);
 
 static struct attribute *dbs_attributes[] = {
@@ -478,6 +531,8 @@ static struct attribute *dbs_attributes[] = {
 	&ignore_nice.attr,
 	&powersave_bias.attr,
 	&io_is_busy.attr,
+	&grad_up_threshold.attr,
+	&early_demand.attr,
 	NULL
 };
 
@@ -525,9 +580,11 @@ static int od_init(struct dbs_data *dbs_data)
 	}
 
 	tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
+	tuners->grad_up_threshold = DEF_GRAD_UP_THRESHOLD;
 	tuners->ignore_nice = 0;
 	tuners->powersave_bias = 0;
 	tuners->io_is_busy = should_io_be_busy();
+	tuners->early_demand = 0;
 
 	dbs_data->tuners = tuners;
 	mutex_init(&dbs_data->mutex);
Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#11 lore raw
Quoted 3 lines · Rafael J. Wysocki

Do you have any numbers indicating that this actually makes things better?

Rafael

No, I don't.
The expected behaviour after this patch is to "force" max frequency few sampling periods earlier. The idea was to increase system responsiveness especially on 'small' embedded systems (phones for example).

Actually, I thought to provide some numbers but I had no idea how to measure this.

Would it be enough to provide the number of times that the CPU increases frequency because of early_demand versus the total number of increments?

Thanks,
Stratos

#12 lore raw
Quoted 5 lines · Stratos Karafotis
Quoted 3 lines · Rafael J. Wysocki

Do you have any numbers indicating that this actually makes things better?

Rafael

Quoted 8 lines

No, I don't.
The expected behaviour after this patch is to "force" max frequency few sampling periods earlier. The idea was to increase system responsiveness especially on 'small' embedded systems (phones for example).

Actually, I thought to provide some numbers but I had no idea how to measure this.

Would it be enough to provide the number of times that the CPU increases frequency because of early_demand versus the total number of increments?

I think it would be better to check if your approach leads to a better behavior as far as energy savings are concerned. If it actually is worse, then I don't see a reason to apply it.

Thanks,
Rafael

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.