Processor affinity on Linux using taskset - linux

I have the following code in a bash script:
echo "bash pid => $$";
echo "processor affinity before => $(taskset -p $$)"
taskset -cp ${AN_INTEGER} $$
echo "processor affinity after => $(taskset -p $$)"
I get this output:
processor affinity before => pid 5047's current affinity mask: ff
pid 5047's current affinity list: 0-7
pid 5047's new affinity list: 1
processor affinity after => pid 5047's current affinity mask: 2
does anyone know what this means?
The reason I started messing with processor affinity is because I would launch multiple bash child processes, and all the bash child process affinities had the value "ff" so it seemed like they were all targeting the same CPU.

The affinity mask controls the set of processors that a process may run on - not a single specific processor. Bits that are a 1 in this mask mean represent a processor that the process can run on. Since you specified that you want this process run on only CPU 1, the affinity mask is now 0b00000010, or 2.

Related

Proper way to use taskset command

I am getting my available CPU that i have with this command
cat /proc/cpuinfo | grep processor |wc -l
It says, i have available 4 cores (actually 2 physical cores and others logicals)
Then i run my task python3 mytask.py from the command line. After run my program, i want to change its pinned core, as only in core0 or core3 or only core0 and core2
I know i can do it with os.sched_setaffinity() function but i want to do that using taskset command
I am trying this ;
taskset -pc 2 <pid> Can i run this command only checking my available CPU number ?
or do i have to check eligible cores for my task before the run taskset command ?
will linux kernel give me a guarantee to accept my new affinity list if it is between 0 and 4 ?
For example i have 4 CPUs available, and when i want to change kworker thread affinity core0 to core1, it failed. Then i checked allowed CPUs for kworker thread with this command ;
cat /proc/6/status |grep "Cpus_allowed_list:"
it says current affinity list: 0
Do i need to check "Cpus_allowed_list" when i want to run taskset command to change affinity list ?

How to change priority of specific thread (LWT) in Linux?

It's possible to see priorities and scheduling policies of all threads of a process like that:
ps H -o 'tid pri cls comm' PID
How to change the individual thread priorities from the command line?
The commands like renice and chrt seem to affect the whole process, but I'm searching the critical path among the threads. Is there maybe anything useful in /proc?
You can use chrt
Example:
sudo chrt -r -p 40 1502
where 40 is the priority and 1502 is the TID
second column from ps -eLo pid,tid,rtprio,ni,comm output

How to run shell commands in parallel without background processes?

I am trying to run several shell commands in a parallel way without making background processes using "&".
Also, I want to assign one job to one CPU (in a fair way)
For example, if I have four cores,
I want assign four cmd1 to cmd4 as follows:
CPU #1: cmd1
CPU #2: cmd2
CPU #3: cmd3
CPU #4: cmd4
Could you please let me know ways doing that?
I've found "parallel" command, but I could not figure out how to use it.
Also, I've tried the following command: ./cmd1 | ./cmd2 | ./cmd3 | ./cmd4
It seems like that four commands (cmd1 to cmd4) are running in parallel, but I am not sure the jobs are assigned to cores as I said in the above.
Thank you!
Sorry. I am running the commands on linux.
First, if you want processes to be executed in parallel, they have to be background jobs. What do have you against using &?
Second, you can use taskset to bind a process to a CPU core, or a set of cores. For example:
taskset -c 0 cmd1 &
taskset -c 1 cmd2 &
taskset -c 2 cmd3 &
taskset -c 3 cmd4 &
This might not be a good idea though; if one process is idle for long periods of time the other 3 cannot use the core it's assigned to.

how to shield a cpu from the linux scheduler (prevent it scheduling threads onto that cpu)?

It is possible to use sched_setaffinity to pin a thread to a cpu, increasing performance (in some situations)
From the linux man page:
Restricting a process to run on a single CPU also avoids the
performance cost caused by the cache invalidation that occurs when a
process ceases to execute on one CPU and then recommences execution on
a different CPU
Further, if I desire a more real-time response, I can change the scheduler policy for that thread to SCHED_FIFO, and up the priority to some high value (up to sched_get_priority_max), meaning the thread in question should always pre-empt any other thread running on its cpu when it becomes ready.
However, at this point, the thread running on the cpu which the real-time thread just pre-empted will possibly have evicted much of the real-time thread's level-1 cache entries.
My questions are as follows:
Is it possible to prevent the scheduler from scheduling any threads onto a given cpu? (eg: either hide the cpu completely from the scheduler, or some other way)
Are there some threads which absolutely have to be able to run on that cpu? (eg: kernel threads / interrupt threads)
If I need to have kernel threads running on that cpu, what is a reasonable maximum priority value to use such that I don't starve out the kernel threads?
The answer is to use cpusets. The python cpuset utility makes it easy to configure them.
Basic concepts
3 cpusets
root: present in all configurations and contains all cpus (unshielded)
system: contains cpus used for system tasks - the ones which need to run but aren't "important" (unshielded)
user: contains cpus used for "important" tasks - the ones we want to run in "realtime" mode (shielded)
The shield command manages these 3 cpusets.
During setup it moves all movable tasks into the unshielded cpuset (system) and during teardown it moves all movable tasks into the root cpuset.
After setup, the subcommand lets you move tasks into the shield (user) cpuset, and additionally, to move special tasks (kernel threads) from root to system (and therefore out of the user cpuset).
Commands:
First we create a shield. Naturally the layout of the shield will be machine/task dependent. For example, say we have a 4-core non-NUMA machine: we want to dedicate 3 cores to the shield, and leave 1 core for unimportant tasks; since it is non-NUMA we don't need to specify any memory node parameters, and we leave the kernel threads running in the root cpuset (ie: across all cpus)
$ cset shield --cpu 1-3
Some kernel threads (those which aren't bound to specific cpus) can be moved into the system cpuset. (In general it is not a good idea to move kernel threads which have been bound to a specific cpu)
$ cset shield --kthread on
Now let's list what's running in the shield (user) or unshielded (system) cpusets: (-v for verbose, which will list the process names) (add a 2nd -v to display more than 80 characters)
$ cset shield --shield -v
$ cset shield --unshield -v -v
If we want to stop the shield (teardown)
$ cset shield --reset
Now let's execute a process in the shield (commands following '--' are passed to the command to be executed, not to cset)
$ cset shield --exec mycommand -- -arg1 -arg2
If we already have a running process which we want to move into the shield (note we can move multiple processes by passing a comma separated list, or ranges (any process in the range will be moved, even if there are gaps))
$ cset shield --shield --pid 1234
$ cset shield --shield --pid 1234,1236
$ cset shield --shield --pid 1234,1237,1238-1240
Advanced concepts
cset set/proc - these give you finer control of cpusets
Set
Create, adjust, rename, move and destroy cpusets
Commands
Create a cpuset, using cpus 1-3, use NUMA node 1 and call it "my_cpuset1"
$ cset set --cpu=1-3 --mem=1 --set=my_cpuset1
Change "my_cpuset1" to only use cpus 1 and 3
$ cset set --cpu=1,3 --mem=1 --set=my_cpuset1
Destroy a cpuset
$ cset set --destroy --set=my_cpuset1
Rename an existing cpuset
$ cset set --set=my_cpuset1 --newname=your_cpuset1
Create a hierarchical cpuset
$ cset set --cpu=3 --mem=1 --set=my_cpuset1/my_subset1
List existing cpusets (depth of level 1)
$ cset set --list
List existing cpuset and its children
$ cset set --list --set=my_cpuset1
List all existing cpusets
$ cset set --list --recurse
Proc
Manage threads and processes
Commands
List tasks running in a cpuset
$ cset proc --list --set=my_cpuset1 --verbose
Execute a task in a cpuset
$ cset proc --set=my_cpuset1 --exec myApp -- --arg1 --arg2
Moving a task
$ cset proc --toset=my_cpuset1 --move --pid 1234
$ cset proc --toset=my_cpuset1 --move --pid 1234,1236
$ cset proc --toset=my_cpuset1 --move --pid 1238-1340
Moving a task and all its siblings
$ cset proc --move --toset=my_cpuset1 --pid 1234 --threads
Move all tasks from one cpuset to another
$ cset proc --move --fromset=my_cpuset1 --toset=system
Move unpinned kernel threads into a cpuset
$ cset proc --kthread --fromset=root --toset=system
Forcibly move kernel threads (including those that are pinned to a specific cpu) into a cpuset (note: this may have dire consequences for the system - make sure you know what you're doing)
$ cset proc --kthread --fromset=root --toset=system --force
Hierarchy example
We can use hierarchical cpusets to create prioritised groupings
Create a system cpuset with 1 cpu (0)
Create a prio_low cpuset with 1 cpu (1)
Create a prio_met cpuset with 2 cpus (1-2)
Create a prio_high cpuset with 3 cpus (1-3)
Create a prio_all cpuset with all 4 cpus (0-3) (note this the same as root; it is considered good practice to keep a separation from root)
To achieve the above you create prio_all, and then create subset prio_high under prio_all, etc
$ cset set --cpu=0 --set=system
$ cset set --cpu=0-3 --set=prio_all
$ cset set --cpu=1-3 --set=/prio_all/prio_high
$ cset set --cpu=1-2 --set=/prio_all/prio_high/prio_med
$ cset set --cpu=1 --set=/prio_all/prio_high/prio_med/prio_low
There are two other ways I can think of doing this (though not as elegant as cset, which doesn't seem to have a fantastic level of support from Redhat):
1) Taskset everything including PID 1 - nice and easy (but, alledgly -- I've never seen any issues myself -- may cause inefficiencies in the scheduler). The script below (which must be run as root) runs taskset on all the running processes, including init (pid 1); this will pin all the running processes to one or more 'junk cores', and by also pinning init, it will ensure that any future processes are also started in the list of 'junk cores':
#!/bin/bash
if [[ -z $1 ]]; then
printf "Usage: %s '<csv list of cores to set as junk in double quotes>'", $0
exit -1;
fi
for i in `ps -eLfad |awk '{ print $4 } '|grep -v PID | xargs echo `; do
taskset -pc $1 $i;
done
2) use the isolcpus kernel parameter (here's the documentation from https://www.kernel.org/doc/Documentation/kernel-parameters.txt):
isolcpus= [KNL,SMP] Isolate CPUs from the general scheduler.
Format:
<cpu number>,...,<cpu number>
or
<cpu number>-<cpu number>
(must be a positive range in ascending order)
or a mixture
<cpu number>,...,<cpu number>-<cpu number>
This option can be used to specify one or more CPUs
to isolate from the general SMP balancing and scheduling
algorithms. You can move a process onto or off an
"isolated" CPU via the CPU affinity syscalls or cpuset.
<cpu number> begins at 0 and the maximum value is
"number of CPUs in system - 1".
This option is the preferred way to isolate CPUs. The
alternative -- manually setting the CPU mask of all
tasks in the system -- can cause problems and
suboptimal load balancer performance.
I've used these two plus the cset mechanisms for several projects (incidentally, please pardon the blatant self promotion :-)), I've just filed a patent for a tool called Pontus Vision ThreadManager that comes up with optimal pinning strategies for any given x86 platform to any given software work loads; after testing it in a customer site, I got really good results (270% reduction in peak latencies), so it's well worth doing pinning and CPU isolation.
Here's how to do it the old-fashioned way, using cgroups. I have a Fedora 28 machine and RedHat/Fedora want you to use systemd-run, but I wasn't able to find this functionality in there. I would love to know how to do it using systemd-run, if anyone would care to enlighten me.
Let's say I want to exclude my fourth CPU (of CPUs 0-3) from scheduling, and move all existing processes to CPUs 0-2. Then I want to put a process on CPU 3 all by itself.
sudo su -
cgcreate -g cpuset:not_cpu_3
echo 0-2 > /sys/fs/cgroup/cpuset/not_cpu_3/cpuset.cpus
# This "0" is the memory node. See https://utcc.utoronto.ca/~cks/space/blog/linux/NUMAMemoryInfo
# for more information *
echo 0 > /sys/fs/cgroup/cpuset/not_cpu_3/cpuset.mems
Specifically, on your machine you'll want to review /proc/zoneinfo and the /sys/devices/system/node heirarchy. Getting the proper node information is left as an exercise for the reader.
Now that we have our cgroup, we need to create our isolated CPU 3 cgroup:
cgcreate -g cpuset:cpu_3
echo 3 > /sys/fs/cgroup/cpuset/cpu_3/cpuset.cpus
# Again, the memory node(s) you want to specify.
echo 0 > /sys/fs/cgroup/cpuset/cpu_3/cpuset.mems
Put all processes/threads on the not_cpu_3 cgroup:
for pid in $(ps -eLo pid) ; do cgclassify -g cpuset:not_cpu_3 $pid; done
Review:
ps -eL k psr o psr,pid,tid,args | sort | cut -c -80
NOTE! Processes currently in sleep will not move. They must be awakened so that the scheduler will put them on a different CPU. To see this, choose your favorite sleeping process in the above list- a process, say a web browser, that you thought should be on CPU 0-2 but it's still on 3. Using its thread ID from the above list, perform:
kill -CONT <thread_id>
example
kill -CONT 9812
Rerun the ps command, and note that it's moved to another CPU.
DOUBLE NOTE! Some kernel threads cannot and will not move! For example, you may note that every CPU has a kernel thread [kthreadd] on it. Assigning processes to cgroups works for userspace processes, not for kernel threads. This is life in the multitasking world.
Now to move a process and all its children to control group cpu_3:
pid=12566 # for example
cgclassify -g cpuset:cpu_3 $pid
taskset -c -p 3 $pid
Again, if $pid is sleeping, you'll need to wake it up for the CPU move to actually take place.
To undo all of this, simply delete the cgroups you've created. Everybody will be stuck back into the root cgroup:
cgdelete -r cpuset:cpu_3
cgdelete -r cpuset:not_cpu_3
No need to reboot.
(Sorry, I don't understand the 3rd question from the original poster. I can't comment on that.)
If you are using rhel instance you can use Tuna for this (May be available for other linux distros also, but not sure about that). It can easily installed from yum command. Tuna can be used to isolate a cpu core and it dynamically moves processes run in that particular cpu to neighboring cpu. The command to isolate a cpu core is as follow,
# tuna --cpus=CPU-LIST --isolate
You can use htop to see how tuna isolate the cpu cores in real-time.

Limiting certain processes to CPU % - Linux

I have the following problem: some processes, generated dynamically, have a tendency to eat 100% of CPU. I would like to limit all the process matching some criterion (e.g. process name) to a certain amount of CPU percentage.
The specific problem I'm trying to solve is harnessing folding#home worker processes. The best solution I could think of is a perl script that's executed periodically and uses the cpulimit utility to limit the processes (if you're interested in more details, check this blog post). It works, but it's a hack :/
Any ideas? I would like to leave the handling of processes to the OS :)
Thanks again for the suggestions, but we're still missing the point :)
The "slowDown" solution is essentially what the "cpulimit" utility does. I still have to take care about what processes to slow down, kill the "slowDown" process once the worker process is finished and start new ones for new worker processes. It's precisely what I did with the Perl script and a cron job.
The main problem is that I don't know beforehand what processes to limit. They are generated dynamically.
Maybe there's a way to limit all the processes of one user to a certain amount of CPU percentage? I already set up a user for executing the folding#home jobs, hoping that i could limit him with the /etc/security/limits.conf file. But the nearest I could get there is the total CPU time per user...
It would be cool if to have something that enables you to say:
"The sum of all CPU % usage of this user's processes cannot exceed 50%". And then let the processes fight for that 50% of CPU regarding to their priorities...
Guys, thanks for your suggestions, but it's not about priorities - I want to limit the CPU % even when there's plenty of CPU time available. The processes are already low priority, so they don't cause any performance issues.
I would just like to prevent the CPU from running on 100% for extended periods...
I had a slightly similar issue with gzip.
Assuming we want to decrease the CPU of a gzip process:
gzip backup.tar & sleep 2 & cpulimit --limit 10 -e gzip -z
Options:
I found sleep useful as the cpulimit sometimes didn't pick up the new gzip process immediately
--limit 10 limits gzip CPU usage to 10%
-z automatically closes cpulimit when gzip process finishes
Another option is to run the cpulimit daemon.
I don't remember and dont think there was something like this in the unix scheduler. You need a little program which controls the other process and does the following:
loop
wait for some time tR
send SIGSTOP to the process you want to be scheduled
wait for some time tP
send SIGCONT to the process.
loopEnd
the ratio tR/tP controls the cpu load.
Here is a little proof of concept. "busy" is the program which uses up your cpu time and which you want to be slowed-down by "slowDown":
> cat > busy.c:
main() { while (1) {}; }
> cc -o busy busy.c
> busy &
> top
Tasks: 192 total, 3 running, 189 sleeping, 0 stopped, 0 zombie
Cpu(s): 76.9% us, 6.6% sy, 0.0% ni, 11.9% id, 4.5% wa, 0.0% hi, 0.0% si
Mem: 6139696k total, 6114488k used, 25208k free, 115760k buffers
Swap: 9765368k total, 1606096k used, 8159272k free, 2620712k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
26539 cg 25 0 2416 292 220 R 90.0 0.0 3:25.79 busy
...
> cat > slowDown
while true; do
kill -s SIGSTOP $1
sleep 0.1
kill -s SIGCONT $1
sleep 0.1
done
> chmod +x slowDown
> slowDown 26539 &
> top
Tasks: 200 total, 4 running, 192 sleeping, 4 stopped, 0 zombie
Cpu(s): 48.5% us, 19.4% sy, 0.0% ni, 20.2% id, 9.8% wa, 0.2% hi, 2.0% si
Mem: 6139696k total, 6115376k used, 24320k free, 96676k buffers
Swap: 9765368k total, 1606096k used, 8159272k free, 2639796k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
26539 cg 16 0 2416 292 220 T 49.7 0.0 6:00.98 busy
...
ok, that script needs some more work (for example, to care for being INTR-upted and let the controlled process continue in case it was stopped at that moment), but you get the point. I would also write that little script in C or similar and compute the cpu ratio from a comand line argument....
regards
I think in Linux there is no solution to cap the cpu usage, but there is an acceptable way to limit any process to a certain CPU usage: http://ubuntuforums.org/showthread.php?t=992706
In case they remove the info, here is again
INSTALL PACKAGES
Install cpulimit package.
Code:
sudo apt-get install cpulimit
Install gawk package.
Code:
sudo apt-get install gawk
CREATE CPULIMIT DAEMON FILE
Open text editor with root privileges and save bellow daemon script text to new file /usr/bin/cpulimit_daemon.sh
Code:
#!/bin/bash
# ==============================================================
# CPU limit daemon - set PID's max. percentage CPU consumptions
# ==============================================================
# Variables
CPU_LIMIT=20 # Maximum percentage CPU consumption by each PID
DAEMON_INTERVAL=3 # Daemon check interval in seconds
BLACK_PROCESSES_LIST= # Limit only processes defined in this variable. If variable is empty (default) all violating processes are limited.
WHITE_PROCESSES_LIST= # Limit all processes except processes defined in this variable. If variable is empty (default) all violating processes are limited.
# Check if one of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST is defined.
if [[ -n "$BLACK_PROCESSES_LIST" && -n "$WHITE_PROCESSES_LIST" ]] ; then # If both variables are defined then error is produced.
echo "At least one or both of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST must be empty."
exit 1
elif [[ -n "$BLACK_PROCESSES_LIST" ]] ; then # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
NEW_PIDS_COMMAND="top -b -n1 -c | grep -E '$BLACK_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
elif [[ -n "$WHITE_PROCESSES_LIST" ]] ; then # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6' | grep -E -v '$WHITE_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
else
NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6 && \$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
fi
# Search and limit violating PIDs
while sleep $DAEMON_INTERVAL
do
NEW_PIDS=$(eval "$NEW_PIDS_COMMAND") # Violating PIDs
LIMITED_PIDS=$(ps -eo args | gawk '$1=="cpulimit" {print $3}') # Already limited PIDs
QUEUE_PIDS=$(comm -23 <(echo "$NEW_PIDS" | sort -u) <(echo "$LIMITED_PIDS" | sort -u) | grep -v '^$') # PIDs in queue
for i in $QUEUE_PIDS
do
cpulimit -p $i -l $CPU_LIMIT -z & # Limit new violating processes
done
done
CHANGE VARIABLES TO YOUR ENVIRONMENT NEEDS
CPU_LIMIT
Change this variable in above script if you would like to omit CPU consumption for every process to any other percentage then 20%. Please read "If using SMP computer" chapter bellow if you have SMP computer (more then 1 CPU or CPU with more then 1 core).
DAEMON_INTERVAL
Change this variable in above script if you would like to have more/less regular checking. Interval is in seconds and default is set to 3 seconds.
BLACK_PROCESS_LIST and WHITE_PROCESSES_LIST
Variable BLACK_PROCESSES_LIST limits only specified processes. If variable is empty (default) all violating processes are limited.
Variable WHITE_PROCESSES_LIST limits all processes except processes defined in this variable. If variable is empty (default) all violating processes are limited.
One or both of the variables BLACK_PROCESSES_LIST and WHITE_PROCESSES_LIST has to be empty - it is not logical that both variables are defined.
You can specify multiple processes in one of this two variables using delimiter characters "|" (without double quotes). Sample: if you would like to cpulimit all processes except mysql, firefox and gedit processes set variable: WHITE_PROCESSES_LIST="mysql|firefox|gedit"
PROCEDURE TO AUTOMATICALLY START DAEMON AT BOOT TIME
Set file permissions for root user:
Code:
sudo chmod 755 /usr/bin/cpulimit_daemon.sh
Open text editor with root privileges and save bellow script to new file /etc/init.d/cpulimit
Code:
#!/bin/sh
#
# Script to start CPU limit daemon
#
set -e
case "$1" in
start)
if [ $(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print $1}' | wc -l) -eq 0 ]; then
nohup /usr/bin/cpulimit_daemon.sh >/dev/null 2>&1 &
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon started successfully"; else print " * cpulimit daemon can not be started" }'
else
echo " * cpulimit daemon can't be started, because it is already running"
fi
;;
stop)
CPULIMIT_DAEMON=$(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print $1}' | wc -l)
CPULIMIT_INSTANCE=$(ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | wc -l)
CPULIMIT_ALL=$((CPULIMIT_DAEMON + CPULIMIT_INSTANCE))
if [ $CPULIMIT_ALL -gt 0 ]; then
if [ $CPULIMIT_DAEMON -gt 0 ]; then
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print $1}' | xargs kill -9 # kill cpulimit daemon
fi
if [ $CPULIMIT_INSTANCE -gt 0 ]; then
ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | xargs kill -9 # release cpulimited process to normal priority
fi
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon can not be stopped"; else print " * cpulimit daemon stopped successfully" }'
else
echo " * cpulimit daemon can't be stopped, because it is not running"
fi
;;
restart)
$0 stop
sleep 3
$0 start
;;
status)
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh" {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon is running"; else print " * cpulimit daemon is not running" }'
;;
esac
exit 0
Change file's owner to root:
Code:
sudo chown root:root /etc/init.d/cpulimit
Change permissions:
Code:
sudo chmod 755 /etc/init.d/cpulimit
Add script to boot-up procedure directories:
Code:
sudo update-rc.d cpulimit defaults
Reboot to check if script starts cpulimit daemon at boot time:
Code:
sudo reboot
MANUALLY CHECK, STOP, START AND RESTART DAEMON
Note: Daemon and service in this tutorial has equal meaning.
Note: For users using prior to Ubuntu 8.10 (like Ubuntu 8.04 LTS) instead of service command use "sudo /etc/init.d/cpulimit status/start/stop/restart" syntax or install sysvconfig package using command: sudo apt-get install sysvconfig
Check if cpulimit service is running
Check command returns: "cpulimit daemon is running" if service is running, or "cpulimit daemon is not running" if service is not running.
Code:
sudo service cpulimit status
Start cpulimit service
You can manually start cpulimit daemon which will start to omit CPU consumption.
Code:
sudo service cpulimit start
Stop cpulimit service
Stop command stops cpulimit daemon (so no new process will be limited) and also sets to all existing limited processes to have full access to CPU, just like it was before cpulimit was not running.
Code:
sudo service cpulimit stop
Restart cpulimit service
If you change some variables settings in /usr/bin/cpulimit_daemon.sh like CPU_LIMIT, DAEMON_INTERVAL, BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST, then after changing settings you must restart service.
Code:
sudo service cpulimit restart
CHECK CPU CONSUMPTION WITH OR WITHOUT CPULIMIT DAEMON
Without daemon
1. stop cpulimit daemon (sudo service cpulimit stop)
2. execute CPU intensive tasks in background
3. execute command: top and check for %CPU column
Result of %CPU is probably more then 20% for each process.
With daemon turned on
1. start cpulimit daemon (sudo service cpulimit start)
2. execute the same CPU intensive tasks in background
3. execute command: top and check for %CPU column
Result of %CPU should be maximum 20% for each process.
Note: Don't forget at beginning %CPU can be more then 20%, because daemon has to catch violating process in interval of 3 seconds (set in script by default)
IF USING SMP COMPUTER
I have tested this code on Intel dual-core CPU computer - that behaves like SMP computer. Don't forget that top command and also cpulimit by default behaves in Irix mode, where 20% means 20% of one CPU. If there are two CPUs (or dual-core) then total %CPU can be 200%. In top command Irix mode can be turned off with command I (pressing +i when top command is running) and Solaris mode is turned on, where total amount of CPU is divided by number of CPUs, so %CPU can be no more then 100% on any number of CPU computer. Please read more info about top command in top man page (search for I command). Please also read more about how cpulimit is operating on SMP computer in cpulimit official page.
But how does cpulimit daemon operates on SMP computer? Always in Irix mode. So if you would like to spend 20% of CPU power on 2-CPU computer then 40% should be used for CPU_LIMIT variable in cpulimit daemon script.
UNINSTALL CPULIMIT DAEMON AND CPULIMIT PROGRAM
If you would like to get rid of cpulimit daemon you can clean up your system by removing cpulimit daemon and uninstalling cpulimit program.
Stop cpulimit daemon
Code:
sudo service cpulimit stop # Stop cpulimit daemon and all cpulimited processes
Remove daemon from boot-up procedure
Code:
sudo update-rc.d -f cpulimit remove # Remove symbolic links
Delete boot-up procedure
Code:
sudo rm /etc/init.d/cpulimit # Delete cpulimit boot-up script
Delete cpulimit daemon
Code:
sudo rm /usr/bin/cpulimit_daemon.sh # Delete cpulimit daemon script
Uninstall cpulimit program
Code:
sudo apt-get remove cpulimit
Uninstall gawk program
If you don't need this program for any other script, you can remote it.
Code:
sudo apt-get remove gawk
NOTE ABOUT AUTHORS
I have just written daemon for cpulimit (bash scripts above). I am not the author of cpulimit project. If you need more info about cpulimit program, please read official cpulimit web page: http://cpulimit.sourceforge.net/.
Regards,
Abcuser
I had a similar problem, and the other solutions presented in the thread don't address it at all. My solution works for me right now, but it is suboptimal, particularly for the cases where the process is owned by root.
My workaround for now is to try very hard to make sure that I don't have any long-running processes owned by root (like have backup be done only as a user)
I just installed the hardware sensors applet for gnome, and set up alarms for high and low temperatures on the CPU, and then set up the following commands for each alarm:
low:
mv /tmp/hogs.txt /tmp/hogs.txt.$$ && cat /tmp/hogs.txt.$$ | xargs -n1 kill -CONT
high:
touch /tmp/hogs.txt && ps -eo pcpu,pid | sort -n -r | head -1 | gawk '{ print $2 }' >> /tmp/hogs.txt && xargs -n1 kill -STOP < /tmp/hogs.txt
The good news is that my computer no longer overheats and crashes. The downside is that terminal processes get disconnected from the terminal when they get stopped, and don't get reconnected when they get the CONT signal. The other thing is that if it was an interactive program that caused the overheating (like a certain web browser plugin!) then it will freeze in the middle of what I'm doing while it waits for the CPU to cool off. It would be nicer to have CPU scaling take care of this at a global level, but the problem is that I only have two selectable settings on my CPU and the slow setting isn't slow enough to prevent overheating.
Just to re-iterate here, this has nothing at all to do with process priority, re-nicing,and obviously nothing to do with stopping jobs that run for a long time. This has to do with preventing CPU utilization from staying at 100% for too long, because the hardware is unable to dissipate the heat quickly enough when running at full capacity (idle CPU generates less heat than a fully loaded CPU).
Some other obvious possibilities that might help are:
Lower the CPU speed overall in the BIOS
Replace the heatsink or re-apply the thermal gel to see if that helps
Clean the heatsink with some compressed air
Replace the CPU fan
[edit]
Note: no more overheating at 100% CPU when I disable variable fan speed in the bios (asus p5q pro turbo). With the CPU fully loaded, each core tops out at 49 celcius.
Using cgroups' cpu.shares does nothing that a nice value wouldn't do. It sounds like you want to actually throttle the processes, which can definitely be done.
You will need to use a script or two, and/or edit /etc/cgconfig.conf to define the parameters you want.
Specifically, you want to edit the values cpu.cfs_period_us and cpu.cfs_quota_us. The process will then be allowed to run for cpu.cfs_quota_us microseconds per cpu.cfs_period_us microseconds.
For example:
If cpu.cfs_period_us = 50000 and cpu.cfs_quota_us = 10000 then the process will receive 20% of the CPU time maximum, no matter what else is going on.
In this screenshot I have given the process 2% of CPU time:
As far as the process is concerned it is running at 100%.
Settings cpu.shares on the other hand can and will still use 100% of the idle CPU time.
In this similar example I have given the process cpu.shares = 100 (of 1024):
As you can see the process is still consuming all the idle CPU time.
References:
http://manpages.ubuntu.com/manpages/precise/man5/cgconfig.conf.5.html
http://kennystechtalk.blogspot.co.uk/2015/04/throttling-cpu-usage-with-linux-cgroups.html
In a system that uses systemd, you can run a single process with a maximum CPU usage using a command like the following:
sudo systemd-run --scope --uid=1000 -p CPUQuota=20% my_heavy_computation.sh
This will use up to 20% of a single CPU core (or CPU thread if using hyper-threading).
I also had the need to limit CPU time for certain processes. Cpulimit is a good tool, but I always had to manually find out the PID and manually start cpulimit, so I wanted something more convenient.
I came up with this bash script:
#!/bin/bash
function lp
{
ps aux | grep $1 | termsql "select COL1 from tbl" > /tmp/tmpfile
while read line
do
TEST=`ps aux | grep "cpulimit -p $line" | wc -l`
[[ $TEST -eq "2" ]] && continue #cpulimit is already running on this process
cpulimit -p $line -l $2
done < /tmp/tmpfile
}
while true
do
lp gnome-terminal 5
lp system-journal 5
sleep 10
done
This example limits the cpu time of each gnome-terminal instance to 5% and the cpu time of each system-journal instance to 5% as well.
I used another script I created named termsql in this example to extract the PID . You can get it here:
https://gitorious.org/termsql/termsql/source/master:
You can limit the amount of cpu time with cgroups. The OS will handle resource management just like you ask for in you question.
Here is a wiki with examples: https://wiki.archlinux.org/index.php/Cgroups
Since the processes already run as a separate user limiting all process from that user should be the easiest solution.
I see at least two options:
Use "ulimit -t" in the shell that creates your process
Use "nice" at process creation or "renice" during runtime
PS + GREP + NICE
The nice command will probably help.
This can be done using setrlimit(2) (specifically by setting RLIMIT_CPU parameter).
Throwing some sleep calls in there should force the process off the CPU for a certain time. If you sleep 30 seconds once a minute, your process shouldn't average more than 50% CPU usage during that minute.
I dont really see why you want to limit the CPU time... you should limit the total load on that machine, and the load is determined by IO operations mostly .
Ex: if i create a while(1){} loop, it will get the total load to 1.0, but if this loop does some disk writes the load jumps to 2.0... 4.0. And that's what killing your machine, not the CPU usage. The CPU usage can be easily handled by nice/renice.
Anyways, you could make a script that does a 'kill -SIGSTOP PID' for a specific PID, when the load gets too high, and kill -SIGCONT when everything gets back to normal... The PID's can be determined by using the 'px aux' command, because i see that it displays the CPU usage, and you should be able to sort the list using that column. I think this the whole thing could be done in bash...
You could scale down the CPU frequency. Then you don't have to worry about the individual processes. When you need more cpu's, scale the frequency back up.

Resources