Disabling CPU Scaling when Profiling Code

Producing consistent results when measuring the performance of C++ in Linux

Disable CPU Scaling for Better Performance Measurement

It’s often necessary to disable the CPU Scaling feature on a system when doing performance measurement in C++.

Here’s how to do it on Linux.

LinkedInTable of Contents

CPU Scaling link icon

Modern CPUs generally all support something called CPU Scaling, where the frequency of the CPU changes to accommodate varying degrees of load on the system. After all, we’re not always doing the most demanding activities. Why should the CPU cores be running at max throttle all of the time?

Scaling is obviously a great invention that should generally be left turned on for the majority of users, but unfortunately it gets in the way of consistent measurements when we’re trying to profile code performance. Since performance measurment often counts CPU cycles, we want the CPU frequency to remain static during measurement, and between iterations of measurement.

\ Google Benchmark will warn you if scaling is enabled while profiling

***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.

Manually disabling CPU scaling link icon

Disabling and re-enabling CPU scaling is done differently on each platform. This article deals with Linux systems, so we’ll focus on how to do it on Linux.

Linux link icon

There are a few commands we can use to report and interact with this feature on Linux, but in general we’ll use the cpupower command (manpages).

Frequency scaling governors link icon

In general, we want to interact with the frequency scaling **governor*n * when it comes to modifying scaling.

TLDR: Generally, “disable” by setting to performance, and then re-enable with schedutil.

There are a number of setting codes, described in the Arch Wiki page.

Governor Description Recommendation
schedutil Scheduler sets freq on-demand Recommended modern default
performance Lock to max frequency Max performance/power use
powersave Lock to min frequency Not many use cases
userspace Application-dependent Highly customizable
ondemand Scales CPU up quickly on load, down when idle Replaced by schedutil
conservative Auto power saving Deprecated in modern systems

Toggling CPU frequency settings on Linux link icon

In my system’s case, in most circumstances, toggling between the two is simple. Check your system’s supported options and decide for yourself which ones to use.

\ DISABLE frequency scaling

# pin to max frequency for all cores
sudo cpupower frequency-set -g performance

\ ENABLE frequency scaling

# set to schedutil (modern default) for all cores
sudo cpupower frequency-set -g schedutil

\ General interaction commands

# list CPU model's supported frequency governors
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors

# query current frequency governor settings, list by core
cpupower frequency-info -o proc

# set all cores to a specified governor setting
cpupower frequency-set -g <setting>

Windows and MacOS link icon

We won’t delve into the details since this is a Linux article, but here is what I could find regarding CPU scaling on these platforms. Drop a comment if you have more information to share!

Windows link icon

There’s probably a way to write a Powershell or other script for this, but the usual way of disabling/enabling scaling is to go into the control panel to the Power Management section and set it there.

MacOS link icon

This seems to be tricky on MacOS. The OS doesn’t natively give access to the APIs needed, so you might have to find a 3rd party application for doing this.

Other ways to influence benchmark performance link icon

Scaling is not the only way to improve determinism and consistency when doing code profiling on a system. On a Linux system, we can occasionally benefit from core-pinning and trying to manually influence the process priority when running the actual benchmark on the compiled binary.

taskset - pinning to a single CPU core link icon

Use taskset (manpages) on Linux to pin a process to a specific single CPU core, so that it doesn’t get split along other cores. This might not be useful for a multithreaded application.

nice - set priority and run link icon

Specify the priority (“niceness”) of the process manually specifying a number for priority with nice (manpages)

Comments