Hi there. I’m trying to limit the number of CPU’s for a heavy task processing job that I’m doing.
I’ve got a 1 CPU machine. However when I query the CPU count using nproc I get 8 cpus, which seems to be the number of CPU’s on the host machine.
I’ve grepped through the cgroups directory and I can’t find anything there. Looking at the environmental variables also yields nothing. Is there a setting I’m missing? If not, can engineering put this in? Seems like it would be a very simple thing to implement.
Are you running a Docker container or using a native runtime? What’s your reason for wanting to limit the number of CPUs used by your application? Also, what technology or programming language are you using?
I’m using the Docker service. My stack is python. But ssh’ing into the instance shows no indication of the number of CPU’s available.
I want to limit the number of CPU’s because each worker was forking the process and blowing up the memory budget and the OS was sending my program a kill -9 to the parent process, orphaning the children which still consumed the memory and this was a painful issue to debug.
A program like ‘nproc’ will count all CPUs available across all machines within the same node/machine. Since you’re on a cloud, your server is in a containerized environment alongside other services.
To get an accurate reading of the available CPUs on your machine, refer to your instance type specs or check cgroups files like ‘/sys/fs/cgroup/cpu.max’, depending on the native runtimes you’re using.
Okay that’s great. Can you add this to the documentation?
It would be best if this can be injected into the environmental variables so commoners like me can simply discover it. Something like RENDER_NUM_CPUS=2 would be amazingly awesome. This path you’ve listed seems highly esoteric and I have no idea it even existed and is not easily discoverable.
This is the output, for anyone that is curious and comes across this problem.
Just so I understand your use case a bit more, why do you need to query the number of CPUs available dynamically? Our instances have static resources, so the number of CPUs, RAM, etc., always remains the same. Since you know the instance type you’re using, why can’t you set the number of CPUs via an environment variable or within the start commands? I understand you might want to configure Gunicorn or other services, but it’s unclear why you need to do this dynamically via code if the resource amounts never change?
import os
import warnings
from pathlib import Path
def _get_render_service_cpu_count() -> int:
"""
The Render.com service provides the number of CPUs via the cgroups.
This file has two values which represent a ratio of the amount of time
that can be scheduled to a process for a given time period. For example,
50000 100000
Represents 50% of the CPU time for a given time period.
As another example, 100000 100000 represents 100% of the CPU time.
And 200000 100000 represents 200% of the CPU time, meaning 2 CPUs.
The minimum number of CPU's this will return is 1.
"""
assert "RENDER" in os.environ, "RENDER environment variable not set"
cpu_max_path = Path("/sys/fs/cgroup/cpu.max")
assert cpu_max_path.exists(), f"File {cpu_max_path} does not exist"
text = cpu_max_path.read_text(encoding="utf-8")
out = text.strip()
first_str, second_str = out.split(" ")
first, second = float(first_str), float(second_str)
num_cpus = first / second
n_num_cpus = int(num_cpus + 0.5)
return max(1, n_num_cpus) # On partial CPUs, return at least 1
def cpu_count() -> int:
try:
_cpu_count = os.environ.get("CPU_COUNT")
if _cpu_count:
return int(_cpu_count)
if "RENDER" in os.environ:
return _get_render_service_cpu_count()
out = os.environ.get("CPU_COUNT", os.cpu_count()) or 1
return int(out)
except Exception as e:
warnings.warn(f"Failed to get CPU count: {e}")
return 1
def unit_test() -> None:
print(f"cpu_count: {cpu_count()}")
if __name__ == "__main__":
unit_test()