Understanding “siblings” in /proc/cpuinfo: Virtual Cores vs Physical Cores Explained


2 views

When examining Linux system information, the /proc/cpuinfo file contains crucial details about your CPU architecture. One field that often causes confusion is "siblings". Here's what it really means:

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 158
model name      : Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
siblings        : 12
cpu cores       : 6

The "siblings" value represents the total number of logical processors available per physical CPU package. This includes:

  • Physical CPU cores
  • Hyper-threading logical cores

For the example above (Intel i7-8750H):

  • 6 physical cores
  • 12 logical processors (with hyper-threading)
  • Therefore siblings = 12

Here's how to programmatically extract and interpret these values in Python:

def get_cpu_info():
    with open('/proc/cpuinfo') as f:
        data = f.read()
    
    info = {}
    for line in data.split('\n'):
        if ':' in line:
            key, val = map(str.strip, line.split(':', 1))
            info[key] = val
    
    siblings = int(info.get('siblings', 1))
    cpu_cores = int(info.get('cpu cores', 1))
    threads_per_core = siblings // cpu_cores
    
    print(f"Physical cores: {cpu_cores}")
    print(f"Logical cores: {siblings}")
    print(f"Threads per core: {threads_per_core}")

get_cpu_info()

Understanding this distinction becomes crucial for:

  • Thread pool configuration
  • Affinity settings in high-performance computing
  • Container resource allocation
  • Benchmarking and performance testing

For instance, when using OpenMP, you might want to set:

export OMP_NUM_THREADS=$(grep -c ^processor /proc/cpuinfo)  # All logical cores
# OR
export OMP_NUM_THREADS=$(grep 'cpu cores' /proc/cpuinfo | head -1 | cut -d: -f2)  # Physical cores only

You can verify the information using other Linux utilities:

lscpu | grep -E 'Core(s)|Socket|Thread'

Or for a quick overview:

nproc --all          # Shows total logical processors
nproc --ignore=1     # Shows total minus 1 (useful for parallel builds)

In Linux systems, the /proc/cpuinfo file contains detailed information about the system's CPU architecture. The "siblings" field specifically indicates the number of logical processors (threads) that the operating system recognizes per physical CPU core. This value reflects the total count of processing units available to the system, including both physical cores and any additional virtual cores created through hyper-threading or similar technologies.

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 158
model name      : Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
stepping        : 9
microcode       : 0x84
cpu MHz         : 2800.000
cache size      : 6144 KB
physical id     : 0
siblings        : 8
core id         : 0
cpu cores       : 4

The key metrics to understand are:

  • cpu cores: Physical processor cores
  • siblings: Logical processors (including hyper-threads)
  • processor: OS-level processor ID

For a CPU with hyper-threading (like Intel's HT Technology), the formula is typically:

siblings = cpu cores × threads per core

Here's how to programmatically extract and interpret these values in Python:

import re

def get_cpu_info():
    with open('/proc/cpuinfo') as f:
        content = f.read()
    
    siblings = int(re.search(r'siblings\t: (\d+)', content).group(1))
    cpu_cores = int(re.search(r'cpu cores\t: (\d+)', content).group(1))
    
    return {
        'physical_cores': cpu_cores,
        'logical_cores': siblings,
        'threads_per_core': siblings // cpu_cores
    }

print(get_cpu_info())

Understanding these values is particularly important for:

  • Task scheduling and thread pool configuration
  • Performance optimization in multi-threaded applications
  • Virtual machine resource allocation
  • Determining true hardware capabilities

On modern NUMA systems, you might need to consider additional factors:

from collections import defaultdict

def analyze_numa_topology():
    physical_ids = defaultdict(int)
    with open('/proc/cpuinfo') as f:
        current_phys_id = None
        for line in f:
            if line.startswith('physical id'):
                current_phys_id = int(line.split(':')[1].strip())
            elif line.startswith('cpu cores') and current_phys_id is not None:
                physical_ids[current_phys_id] = int(line.split(':')[1].strip())
    
    return dict(physical_ids)

print(analyze_numa_topology())