Assuming Linux, and assuming the current shell was started possibly restricted with taskset, I can write some code to get the current process affinity as
#include <vector>
#include <pthread.h>
#include <stdio.h>
int getNumberOfAvailableCores() {
pthread_t self = pthread_self();
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
int res = ::pthread_getaffinity_np(self, sizeof(cpuset), &cpuset);
int num_cores = 0;
if ( res!=0 ) return -1;
for (int j = 0; j < CPU_SETSIZE; j++) {
if (CPU_ISSET(j, &cpuset)) ++num_cores;
}
return num_cores;
}
int main() {
int num_cores = getNumberOfAvailableCores();
printf( "%d\n", num_cores );
return 0;
}
https://godbolt.org/z/TxT67WWT6
But on machines where I do not even a compiler installed, is there any way to guess the number of available cores?
getconf _NPROCESSORS_ONLN will return the number of processors online, but will not take in consideration the number of cores isolated. Same for grepping /proc/cpuinfo or lscpu.
I looked into /proc/self but would not find a clean way to do it.
You want the command nproc:
nproc - print the number of processing units available
Example where the affinity mask contains 3 processors:
$ taskset --cpu-list 0,2,4 bash
$ nproc
3
My old answer may be useful in case nproc isn't available for some reason:
The
tasksetcommand is used to set or retrieve the CPU affinity of a running process given its pid
And the -p option for taskset says:
So, you get a hex number with the affinity mask for your process. Example:
$ taskset -p $$
pid 1643922's current affinity mask: fff
Now, you want to do a popcount (count the number of 1s in the binary representation of the number).
The idea is then to convert the number into its binary form and then count the number of 1s. Here's a one-liner:
taskset -p $$ | \
tr '[[:lower:]]' '[[:upper:]]' | \
sed -E 's/.*:\s*/ibase=16;obase=2;/' | bc | tr -d '0\n' | wc -c
tr '[[:lower:]]' '[[:upper:]]' - converts the output from taskset into uppercase (because bc needs uppercase hexadecimal numbers).sed -E 's/.*:\s*/ibase=16;obase=2;/' - remove the textual output from taskset and replace it with instructions for bc. ibase is the base of the input number (16 = hex) and obase is the base we want for the output (2 = binary).
ibase=16;obase=2;FFFbc - Reads ibase=16;obase=2;FFF and prints FFF as 111111111111tr -d '0\n' - Deletes all zeroes and the newline from the output from bcwc -c - count all characters.In my case, where the affinity mask is fff, the output is 12.
Testing: I here start a subshell with 3 processors available and then use the oneliner above from within that shell to figure this out:
$ taskset --cpu-list 0,2,4 bash
$ taskset -p $$ | \
> tr '[[:lower:]]' '[[:upper:]]' | \
> sed -E 's/.*:\s*/ibase=16;obase=2;/' | bc | tr -d '0\n' | wc -c
3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With