3

I have a process doing some computation the whole time. It causes my system's CPU to heat up and the fan to spin faster.

I want this process to run, but with a low priority. I don't want my system to heat up and my fan to spin because of it. Is it possible to achieve this?

If it matters, my CPU is an AMD Ryzen 5 3500U and the process is a browser tab (I'm running it in Chromium, but am happy to change browser if it helps). I'm willing to even run the whole browser inside a VM if it helps.


What I tried and why it failed:

  1. The best solution found so far is limiting the maximum CPU frequency:

    echo 0 > /sys/devices/system/cpu/cpufreq/boost
    cpupower frequency-set -u 1200MHz
    

    It works, but it means that other processes are affected too: compiling, (un)compressing etc takes way longer.
    Moreover, the CPU is still warmer than if the process wasn't running. Although to acceptable temperatures.

  2. cpulimit cripples the performance of the target process.
    If I set the percentage of CPU allowed to 50% (cpulimit -l 50 -p ...), the computation becomes a lot slower than normal (like 10x as slow; I don't have a good way to measure the accurate slowdown).

  3. I played around with cgroups for a bit, but couldn't get any effect.

  4. Nice has no effect of course.

Is there anything else I should try?

peoro
  • 3,778
  • 1
    You want to limit CPU-heat without slowing performance? cpulimit -l 50 means that it uses 50% of one core (3500U has 8 virtual cores), which of course slows the process. Less heat witn same performance won't work. – stoney Aug 19 '20 at 07:20
  • I'm happy to slow the performance of this specific process, not of the whole system. cpulimit -l 50 is slowing the proces way way more than the 50% I request. – peoro Aug 19 '20 at 07:37
  • then try cpulimit -L 400 which should more or less limit the process to 50% of cpu capacity (try playing with the number if not satisfied) – stoney Aug 19 '20 at 07:39
  • The process is single threaded. When unlimited it uses 100% of one core. It keeps using 100% of one core even if I run cpulimit -l 100. – peoro Aug 19 '20 at 07:42
  • The only thing that comes to mind here is context-switches. Try to bind it to a cpu then like described here and use cpulimit to limit the amount of cpu used. Might or might not help. – stoney Aug 19 '20 at 07:48
  • Pinning the process doesn't seem to help either... The process still runs way slower with the CPU at maximum frequency (2.4GHz) and cpulimit at 50%, than it does with the CPU capped at 1.2GHz and no cpulimit... – peoro Aug 19 '20 at 08:32
  • CPU energy consumption is mostly attributed to logic gate (transistor) switching. This means that computation costs energy. A given processing job will take a fixed number of CPU cycles to complete so a single job has a "fixed" total energy cost. Power = Energy / Time. So if you want 50% power, your process will take 2x as long. The only exception to this can be CPU speed. The faster a CPU clocks, the less energy efficient it is. Clock it slower and you might get more CPU cycles for your energy. Not all CPU's achieve this advantage to clocking slower. – Philip Couling Aug 19 '20 at 15:51
  • I'm not too concerned about energy consumption. Mostly I'm bothered by the noise of the fan. – peoro Aug 19 '20 at 21:08

2 Answers2

3

I found out that some governors (ondemand and conservative) support a flag to ignore processes with a positive nice value when choosing to scale up or down.

From the kernel.org CPUFreq Governors documentation:

ignore_nice_load:

This parameter takes a value of '0' or '1'. When set to '0' (its default), all processes are counted towards the 'cpu utilisation' value. When set to '1', the processes that are run with a 'nice' value will not count (and thus be ignored) in the overall usage calculation. This is useful if you are running a CPU intensive calculation on your laptop that you do not care how long it takes to complete as you can 'nice' it and prevent it from taking part in the deciding process of whether to increase your CPU frequency.

I loaded the ondemand governor, enabled its ignore_nice_load flag and set a nice value to the low-priority always-computing process:

# load and enable the ondemand governor
sudo modprobe cpufreq_ondemand
sudo cpupower frequency-set -g ondemand

enable ignore_nice_load

echo 1 | sudo tee /sys/devices/system/cpu/cpufreq/ondemand/ignore_nice_load

set a nice value to the target process

renice -n 19 -p PID

Now all my cores remain cool (and the fan is quiet) all the time in spite of the always computing process taking 100% of a core. They immediately scale up whenever something else needs a lot of computational power.

peoro
  • 3,778
2

Linux allows to set maximum frequency per CPU core, so if I were you I'd do the following:

echo 2100000 | sudo tee /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq`

(other possible values are 1700000 and 1400000)

Then pin this CPU intensive task to the first core (usually called "setting a CPU affinity" under Unix):

sudo taskset -cp 0 $PID