Getting Started Guide¶
Overview¶
PyHwloc
exposes a Python interface to the Hardware Locality (hwloc) library, providing
an easier and more interactive way to discover and control your system’s hardware
topology. For a comprehensive introduction to hardware topology concepts and background
information, please refer to the official hwloc documentation. This document primarily concerns the usage
of the Python interface.
Two-Tier Architecture
PyHwloc is designed with two layers:
High-Level Interface (Recommended): Provides Pythonic classes and methods that are easy to use and follow Python conventions, but has limited feature set at the moment.
Low-Level Interface: Direct mapping of the C API through
ctypes
for advanced use cases when high-level features are insufficient.
Most users should start with the high-level interface and only use the low-level API when
specific functionality is missing. Two interfaces can interpolate through the use of the
native_handle
property.
Warning
This project is still working in progress.
Warning
This document site is temporary, we might migrate in the future.
Quick Start Example¶
Here’s a simple example to get started with pyhwloc
:
from pyhwloc import from_this_system
# Create and load system topology
with from_this_system() as topo:
# Get basic system information
n_cores = topo.n_cores()
n_numa = topo.n_numa_nodes()
print(f"System has {n_cores} CPU cores")
print(f"System has {n_numa} NUMA nodes")
# Get current CPU binding
cpuset = topo.get_cpubind()
print(f"Current CPU binding: {cpuset}")
We have some more examples in the Gallery.
Tips and Tricks¶
Documentation¶
We reuse the C document for most of the functions, which might look confusing if you are not already familiar with hwloc. On the other hand, the package is fully typed. Please use the type hints as part of the document.
The Topology Class and the Object Class¶
The hwloc API is built upon the Topology
, through which one
can obtain devices represented by the Object
and other
attributes. For interpolation with CUDA libraries, the Device
can be converted into a Object
through the
topology. Following is a snippet for walking the topology with object nodes:
import pyhwloc
with pyhwloc.Topology() as topo:
for node in topo.iter_numa_nodes():
print(f"NUMA Node {node.logical_index}: {node}")
print(f" Memory: {node.total_memory // (1024 * 1024)} MB")
The Object
represents a specific software or hardware device
in the device tree. You can get its attributes using specific getters like
arity
.
We have some special categories of objects, including
NumaNode
, OsDevice
and
friends. These object types have their own attributes, like the PCI bus ID of the
PciDevice
. You can check whether an object is an OsDevice
by using the isinstance
, or the predicate
is_os_device()
. Iteration methods like the
iter_numa_nodes shown above can return object types with the correct type
annotation. Other methods return the generic Object type hint, but the underlying type
is still valid (can be checked with isinstance
). To put it concretely:
Use iterator with known type:
import pyhwloc
from pyhwloc.hwobject import NumaNode
with pyhwloc.from_this_system() as topo:
for node in topo.iter_numa_nodes():
assert isinstance(node, NumaNode)
# Local memory is specific to the NumaNode object type.
print(f"Local memory: {node.local_memory // (1024 * 1024)} MB")
Use runtime-defined object type:
import pyhwloc
from pyhwloc.hwobject import NumaNode, Object
with pyhwloc.from_this_system() as topo:
# We don't know what the child is.
for child in topo.iter_all_breadth_first():
if child.is_numa_node():
# The type is always the most specialized type.
assert isinstance(child, NumaNode)
# NumaNode is a sub-class of the Object
assert isinstance(child, Object)
Working with Enum Flags¶
PyHwloc uses enums extensively for options and flags, following hwloc’s C API design. We provide some syntax sugar to work with these flags in Python.
Simple Enums
For basic enum values, you can work with them like standard Python enums:
from pyhwloc.topology import MemBindPolicy
# Use enum values directly (integer 2)
policy = MemBindPolicy.BIND
# Get human-readable name
policy_name = MemBindPolicy(policy).name
print(f"Policy: {policy_name}")
Composite Flags
Some flags can be combined using bitwise OR operations. pyhwloc
provides convenient
ways to work with these:
from pyhwloc.topology import MemBindFlags
from pyhwloc import Topology
with Topology.from_this_system() as topo:
# Method 1: Pass a list of flags (recommended)
topo.set_membind(
target_set,
MemBindPolicy.BIND,
[MemBindFlags.STRICT, MemBindFlags.THREAD],
)
# Method 2: Use bitwise OR manually
combined_flags = MemBindFlags.STRICT | MemBindFlags.THREAD
topo.set_membind(
target_set,
MemBindPolicy.BIND,
combined_flags,
)
Please note that you can’t create an instance of MemBindFlags
with the combined
here. The composite value is not a valid Python enum. We are using integer values after
the composition.
Testing Flag Membership
To check if a specific flag is present in a composite flag value:
# Check if a flag is set
is_strict = bool(flags & MemBindFlags.STRICT)
Using the Bitmap¶
The Bitmap
is a core data structure used by hwloc. One can
convert the bitmap into a Python set using the
to_sched_set()
for interpolation with the Python
os.sched_
module. Similarly, one can construct a bitmap from a integer set:
import os
from pyhwloc.bitmap import Bitmap
affinity = os.sched_getaffinity(0)
cpuset = Bitmap.from_sched_set(affinity)
print(cpuset)