Skip to content

CPU Core Counting results (2025‐01‐17)

Austin E. Soplata edited this page Jan 17, 2025 · 1 revision

Here are results that illustrate the logic behind our new CPU core detection (including hardware-threading) and selection, based on https://github.com/jonescompneurolab/hnn-core/pull/871 , specifically this comment: https://github.com/jonescompneurolab/hnn-core/pull/871#issuecomment-2542373540 .

Test script

For all the below, I've shown the results of running the following script, which will run if you switch to the brown-ccv/gui-mpi-available-cores branch:

#!/usr/bin/env python

from hnn_core.parallel_backends import _determine_cores_hwthreading
import psutil

### Get all counts of the machine #############################################

# "Logical" count: This should include hardware-threaded cores as separate cores, if they're available.
print(f"psutil.cpu_count(logical=True) = {psutil.cpu_count(logical=True)}")

# "Physical" count: This should NOT include hardware-threaded cores as separate cores, even if they're available.
print(f"psutil.cpu_count(logical=False) = {psutil.cpu_count(logical=False)}")

# "Affinity" count: This should return the Logical count, except on MacOS where it doesn't work, and except on Oscar/HPC where it returns your requested allocation number of cores.
try:
    print(f"len(psutil.Process().cpu_affinity()) = {len(psutil.Process().cpu_affinity())}")
except AttributeError as e:
    print(e)

### Compare all cases of our core detection function ##########################

# This is the default case, and should return the Logical or Affinity depending on platform.
print(f"_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=False) = {_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=False)}")

# This should return the Physical count
print(f"_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=False) = {_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=False)}")
print(f"_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=True) = {_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=True)}")
print(f"_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=True) = {_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=True)}")

MacOS (Intel)

  • Hardware details:

    • OS: MacOS 15.0.1
    • CPU: 2.3 GHz Quad-Core Intel Core i5 (MacBook Pro 2018, so probably i5-8259U. 4 physical cores, 8 logical cores ("threads") via Intel Hyperthreading)
  • Test script output:

psutil.cpu_count(logical=True) = 8
psutil.cpu_count(logical=False) = 4
'Process' object has no attribute 'cpu_affinity'
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=False) = [8, True]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=False) = [4, False]
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=True) = [7, True]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=True) = [3, False]

MacOS (Apple Silicon)

  • Hardware details:

    • OS: MacOS 15.2
    • CPU: Apple M4 Pro (12 cores, no hardware-threading capability)
  • Test script output:

psutil.cpu_count(logical=True) = 12
psutil.cpu_count(logical=False) = 12
'Process' object has no attribute 'cpu_affinity'
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=False) = [12, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=False) = [12, False]
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=True) = [11, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=True) = [11, False]

Linux (Intel)

  • Hardware details:
    • OS: Kubuntu 24.04
    • CPU: Intel® Core™ i7-10710U CPU @ 1.10GHz (6 physical cores, has Intel Hyperthreading for 12 logical cores)
  • Test script output:
psutil.cpu_count(logical=True) = 12
psutil.cpu_count(logical=False) = 6
len(psutil.Process().cpu_affinity()) = 12
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=False) = [12, True]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=False) = [6, False]
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=True) = [11, True]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=True) = [5, False]

Oscar HPC (Intel)

psutil.cpu_count(logical=True) = 48
psutil.cpu_count(logical=False) = 48
len(psutil.Process().cpu_affinity()) = 48
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=False) = [48, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=False) = [48, False]
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=True) = [12, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=True) = [12, False]
  • Test script output for allocation via salloc --nodes=1 --ntasks-per-node=4 --time=10 (note that only the Affinity core count is accurate with respect to our allocation, and what we should use vs Logical or Physical):
psutil.cpu_count(logical=True) = 24
psutil.cpu_count(logical=False) = 24
len(psutil.Process().cpu_affinity()) = 4
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=False) = [4, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=False) = [4, False]
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=True) = [3, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=True) = [3, False]
  • Test script output for allocation via salloc --nodes=2 --ntasks-per-node=4 --time=10 (note that our current core detection does NOT detect available cores across Oscar nodes. This has likely always been true.):
psutil.cpu_count(logical=True) = 24
psutil.cpu_count(logical=False) = 24
len(psutil.Process().cpu_affinity()) = 4
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=False) = [4, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=False) = [4, False]
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=True) = [3, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=True) = [3, False]

Windows (AMD)

  • Please note that Windows is a special case, and as noted in the code for https://github.com/jonescompneurolab/hnn-core/pull/871 and elsewhere (such as https://github.com/jonescompneurolab/hnn-core/issues/589 ), MPI is not currently supported on Windows. This is why, in _determine_cores_hwthreading, I have forced off detection of hwthreading, even if it is present.
  • Hardware details:
    • OS: Windows 11 Home 23H2
    • CPU: AMD Ryzen 7 7735HS with Radeon Graphics 3.20 GHz (Does have support for hardware threading, physical cores 8, logical cores 16).
  • Test script output:
psutil.cpu_count(logical=True) = 16
psutil.cpu_count(logical=False) = 8
len(psutil.Process().cpu_affinity()) = 16
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=False) = [8, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=False) = [8, False]
_determine_cores_hwthreading(enable_hwthreading=True, sensible_default_cores=True) = [7, False]
_determine_cores_hwthreading(enable_hwthreading=False, sensible_default_cores=True) = [7, False]