The difference is that PR is a real priority of a process at the moment inside of the kernel and NI is just a hint for the kernel what the priority the process should have.
In most cases PR value can be computed by the following formula: PR = 20 + NI. Thus the process with niceness 3 has the priority 23 (20 + 3) and the process with niceness -7 has the priority 13 (20 - 7). You can check the first by running command
nice -n 3 top. It will show that top process has NI 3 and PR 23. But for running
nice -n -7 top in most Linux systems you need to have root privileges because actually the lower PR value is the higher actual priority is. Thus the process with PR 13 has higher priority than processes with standard priority PR 20. That's why you need to be root. But minimum niceness value allowed for non-root process can be configured in /etc/security/limits.conf.
Theoretically the kernel can change PR value (but not NI) by itself. For example it may reduce the priority of a process if it consumes too much CPU, or it may increase the priority of a process if that process had no chance to run for a long time because of other higher priority processes. In these cases the PR value will be changed by kernel and NI will remain the same, thus the formula "PR = 20 + NI" will not be correct. So the NI value can be interpreted as hint for the kernel what the priority the process should have, but the kernel can choose real priority (PR value) on its own depending on the situation. But usually the formula "PR = 20 + NI" is correct.
Exact rules how the kernel changes priority aren't clear. setpriority (the function that change nice value) manual says:
The effect of changing the nice value may vary depending on the process-scheduling algorithm in effect.
Pthread manual says the following:
The dynamic priority is based on the nice value (set by nice(2), setpriority(2), or sched_setattr(2)) and increased for each time quantum the thread is ready to run, but denied to run by the scheduler.
It seems that PR value corresponds to dynamic priority.
The range of the NI value is -20..19. Thus the PR value can have the values from 0 (20 - 20) to 39 (20 + 19). But it is correct only for the processes with default scheduling policy (SHED_OTHER). There may be also processes with so called "real time" scheduling policies. These policies are SCHED_RR and SCHED_FIFO. Such processes have a PR value less than 0. You can check this by running
chrt -r 1 top command (need to be root). The top process will have PR -2. You even can run
chrt -r 90 top in which case the top process will have PR -91.
It seems that for SCHED_RR processes the PR value can be calculated by the formula:
PR = - 1 - sched_rr_priority.
Thus a SCHED_RR process has at least PR -1 which means that any SCHED_RR process has higher priority than any SCHED_OTHER. This corresponds to pthread manual:
SCHED_FIFO can be used only with static priorities higher than 0, which means that when a SCHED_FIFO threads becomes runnable, it will always immediately preempt any currently running SCHED_OTHER, SCHED_BATCH, or SCHED_IDLE thread.
SCHED_RR is a simple enhancement of SCHED_FIFO. Everything described above for SCHED_FIFO also applies to SCHED_RR,
The priority of real time processes is referred as static priority that cannot be changed by the kernel. So positive PR values can be treated as dynamic priority for non-realtime (SCHED_OTHER, SCHED_BATCH) processes and negative PR value as static priority for realtime processes (SCHED_RR, SCHED_FIFO).
I also tried to run
nice -n 10 chrt -r 50 top (and
chrt -r 50 nice -n 10 top). The NI value was 10, but the PR still was -51. So it seems that NI value doesn't affect priority of SCHED_RR processes. This corresponds to setpriority manual:
Any processes or threads using SCHED_FIFO or SCHED_RR shall be unaffected by a call to setpriority(). This is not considered an error. A process which subsequently reverts to SCHED_OTHER need not have its priority affected by such a setpriority() call.
One funny note. If you run
chrt -r 99 top, you will see RT value instead of a number in PR column.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28489 root RT 0 2852 1200 896 R 0 0.1 0:00.01 top
I don't think that this means that the process is now special. I thinks that this means that top just don't print -100 because it would take 4 character to print.
You can also use htop instead of top in all examples which can be more convenient.
ps -l can be used too, but it base point that separates realtime and non-realtime priorities is not 0, but 60, so
nice -n -20 ps -l will print
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 R 0 28983 28804 0 60 -20 - 1176 - pts/6 00:00:00 ps