Linux: Why does the CPU frequency fluctuate when using the performance governor

benchmarkcentral-processing-unitlinuxlinux-kernelperformance

I'm using a Debian 8 amd64 machine for benchmarking. During experimentation, I would like the CPU to operate at a fixed frequency (preferably the maximum possible). This will rule out the CPU clock speed as a source of variation in the results.

After some reading, it seems that the correct thing to do is to change the CPU governor to performance, which is described here in the Linux kernel documentation:

The CPUfreq governor "performance" sets the CPU statically to the
highest frequency within the borders of scaling_min_freq and
scaling_max_freq.

Sadly, further details about scaling_min_freq and scaling_max_freq are not supplied. Hopefully it should not matter, as the CPU frequency used is the maximum value of the interval.

So I've enabled this governor using cpufreq-set:

$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
performance
performance
performance
performance

And for good measure, I also disabled turbo boost mode in the bios:

$ cat /sys/devices/system/cpu/intel_pstate/no_turbo
1

Based on the above description of the performance governor, I would expect no fluctuation in the CPU clock speed. Yet if I repeatedly run cpufreq-info, I see the clock speed fluctuating:

$ cpufreq-info | grep 'current CPU fr'
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 3.99 GHz.
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 4.00 GHz.
$ cpufreq-info | grep 'current CPU fr'
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 3.96 GHz.
$ cpufreq-info | grep 'current CPU fr'
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 3.94 GHz.
$ cpufreq-info | grep 'current CPU fr'
  current CPU frequency is 4.01 GHz.
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 4.00 GHz.
  current CPU frequency is 3.98 GHz.

Is this fluctuation due to hardware, the BIOS, the kernel, or some other factor? Is there a way to set the CPU frequency such that it doesn't fluctuate at all?

Best Answer

After some experimentation, I think I can answer my own question.

As mentioned in this thread, on certain Intel hardware, there are two ways to manage the CPU frequency:

  • Using pstate.
  • Using regular ACPI.

When pstate is used, the BIOS has some say over the clock speed, and it seems that this is the source of the fluctuations.

You can force pstate off by appending intel_pstate=disable to the kernel arguments (edit /etc/default/grub and add the arg to GRUB_CMDLINE_LINUX_DEFAULT. Finally run sudo update-grub).

After doing this, the output of cpufreq-info looks much different, and I also notice that a different set of CPU governors become available (e.g. ondemand is now available).

Most importantly, after setting the governor to performance, the clock speed is now fixed (in my case to 4.00GHz).

You can look in /sys/devices/system/cpu/cpu*/cpufreq/scaling_driver to determine if pstate or ACPI is being used to scale the CPU. These files can assume the values acpi-cpufreq or intel_pstate.