CLI tool
open-mpi/hwloc avatar
open-mpi/hwloc

hwloc: the library that tells your program where the cores and memory are

Hardware locality (hwloc)

749 stars218 forksCNOASSERTION

At a glance

What is it?
A C library and set of command line tools for discovering the hardware topology of a machine, from NUMA nodes and caches down to processing units, plus a C API for binding work onto it. It is infrastructure that disappears into Open MPI and a dozen other projects, and it is maintained under a custom licence you need to read.
Who is it for?
Adopt hwloc if you are writing a scheduler, a runtime or an HPC application that needs to know where memory and cores sit relative to each other, since hand rolling that logic is a large and error prone job. Do not adopt it if you only need the processor count, because on unsupported operating systems hwloc reports the number of processors and no topology at all.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem is that a machine is a tree, not a number

The Hardware Locality project aims at easing the process of discovering hardware resources in parallel architectures. It offers command line tools and a C API for consulting those resources, their locality, attributes and interconnection.

What that means concretely is that hwloc gives you a hierarchical map of the key computing elements within a node: NUMA memory nodes, shared caches, processor packages, dies and cores, processing units, meaning logical processors or threads, and even I/O devices. Alongside the structure it gathers attributes such as cache and memory information.

The reason this is not trivial is that the number of processors tells you almost nothing about where those processors are. On a 4 package, 2 core machine with hyper-threading, a naive runtime sees 16 logical processors and no idea that they live in four packages with different L2 caches attached to different NUMA nodes. Code that ignores that gets a performance surprise on a machine that reports the same core count as a laptop.

The project primarily aims at helping high-performance computing applications, but it is also applicable to any project seeking to exploit code and data locality on modern computing platforms. The audience is therefore wider than HPC: anyone binding threads, planning work per socket, or sharding data by locality needs this.

The documentation is hosted at the project site, and the repository README is explicitly described as a truncated and poorly formatted version of that documentation main page, which is worth knowing before you treat the README as the reference.

The tree is the API, and cpusets are the currency

The programming interface is a C API centred on a hierarchy of objects, and two design choices matter to a user.

The first is that the basic interface lives in hwloc.h, while higher-level functions live in hwloc/helper.h to reduce the need to manually manipulate objects and follow links between them. There is also hwloc/inlines.h, which contains the actual inline code of some hwloc.h routines, so a debugger stepping into a call may land in a header rather than a source file. The documentation carries higher-level topology traversal examples, and a Terms and Definitions section that the project says should probably be read first, because the vocabulary is precise.

The second is the cpuset. Each hwloc object contains a cpuset describing the list of processing units, and hwloc brings what the documentation calls a powerful CPU bitmap API used to describe where topology objects sit on physical or logical processors. That is the mechanism you use for binding applications onto certain cores or memory nodes, and it is why the API is usable for placement rather than only for reporting.

Several utility programs are also provided to ease command line manipulation of topology objects, binding of processes and similar tasks.

The text output makes the shape concrete. On a machine with two packages, two cores each and hyper-threading, the tree prints as a nesting of Package, L3, L2, L1, Core and PU levels, with the PU lines carrying processor identifiers such as P#0 and P#8, which is where the non-contiguous numbering of a hyper-threaded machine shows up.

Bindings for several other languages are available from the project website.

Checking your machine with lstopo before you build anything

There is a practical piece of advice in the documentation that answers the question most people actually have, which is whether hwloc will work on their machine at all. To check whether hwloc works on a particular machine, just try to build it and run lstopo or lstopo-no-graphics:

bash
lstopo-no-graphics

If some things do not look right, for example bogus or missing cache information, the documentation points at its Questions and Bugs section.

That is a good workflow because lstopo is a view of the same data the library will give you. If lstopo-no-graphics shows the tree you expect on your hardware, your application will see the same tree. The no-graphics variant matters on machines without an X11 display, which includes most servers and most containers.

The output is not just a tree. The tool can display the topology in a human-readable format, either in graphical mode under X11, or by exporting in several formats, and the documentation lists plain text, LaTeX tikzpicture, PDF, PNG and FIG. Some of those export formats need extra support libraries, which is worth knowing before you wire a PDF export into a report generator.

There is also a textual form of the output for a 4 package, 2 core machine with hyper-threading, which is the clearest illustration of the object model in the whole documentation set. The XML form exists too, and the documentation is candid that it is meant for exporting and importing topologies and is hardly readable to human beings.

Fake topologies for testing, and XML for moving machines around

Two development features are worth knowing about, and they exist because topology discovery is a component you cannot control on a test machine.

The first is fake topologies. For development and debugging purposes, hwloc offers the ability to work on them. A symmetrical tree of resources generated from a list of level arities is one form, documented under synthetic topologies. The other is remote machine simulation through the gathering of topology as XML files, which ties into the XML import and export path.

This is the feature that makes hwloc testable in a normal CI setup. A test can construct a four package, two core, hyper-threaded machine in memory and run placement logic against it, instead of needing a real NUMA box or hoping the CI runner has one. The synthetic form is a symmetrical tree, so it does not model asymmetry, but it covers the tree walking and the cpuset arithmetic.

The XML path serves a second purpose in production. Because a topology can be gathered on one machine and imported on another, a job scheduler can capture the topology of a node at allocation time and hand that description to the application, rather than making every application rediscover the machine independently.

Neither feature is a toy. Topology discovery code is notoriously hard to exercise, and hwloc is one of the few projects in this space that offers a documented way to fake it.

Portability comes from the operating system, not the processor

The portability story is unusual and worth understanding, because it explains both the wide platform list and the one awkward exception.

Since it uses standard operating system information, hwloc's support is mostly independent from the processor type, x86, powerpc and so on, and just relies on operating system support. The main exception is the BSD family, because NetBSD, FreeBSD and similar systems do not provide CPU topology information, so hwloc uses an x86-only CPUID based backend there, which the documentation notes can also be used for other operating systems.

The supported operating system list is long: Linux, with knowledge of cgroups and cpusets, memory targets and initiators, and more, on all supported hardware including Intel Xeon Phi, ScaleMP vSMP and NumaScale NumaConnect; Solaris with support for processor sets and logical domains; AIX; Darwin and OS X; FreeBSD and its variants such as kFreeBSD/GNU; NetBSD; and Microsoft Windows.

The failure mode is stated without hedging. On unsupported operating systems, hwloc only reports the number of processors, and no topology information is available. That is a graceful degradation rather than a crash, and it is exactly the kind of behaviour that hides a problem until someone wonders why their placement optimisation stopped working.

The project tree shows how the implementation is organised, with a hwloc directory holding the library sources, a utils directory for the command line tools, a contrib directory, tests, a config directory, and the usual autotools build files including configure.ac, Makefile.am and autogen.sh. The library is also packaged through a pkg-config file template, hwloc.pc.in, which is how a dependent project finds the include paths and link flags.

What the licence situation means for you

The licence is not a standard one, and that is a deliberate feature of this project rather than an oversight.

The repository is recorded as licensed under a custom licence that GitHub cannot classify, with a pointer to the LICENSE file. The tree carries both a COPYING file and a LICENSE file, alongside an AUTHORS file, a HACKING file, a VERSION file and a NEWS file, which is the conventional layout of a project with a long and careful release process rather than a quick shared repository.

What this means practically is that you have to read the LICENSE file yourself. There is no short identifier to quote, no SPDX expression to put in your package metadata without checking, and no assumption of a permissive grant that you can rely on. A project that has been in continuous development since before the SPDX era, and that is hosted by the Open MPI project, has its own terms, and they are in the file.

The right advice is not a legal opinion but a process one: before you vendor hwloc into a product, read the LICENSE and the COPYING file and confirm they permit what you intend. If you need a machine readable identifier for your own build metadata, deriving one from that text is a decision you have to make rather than assume.

The project is not archived, and the last push was on 2026-10-15. The release history is steady, with hwloc-2.12.2 on 2025-09-16, hwloc-2.13.0 on 2026-02-09 and hwloc-2.14.0 on 2026-06-09, and the releases are distributed from the project site rather than as GitHub release artefacts.

When a simpler answer is the right one

There are cases where hwloc is clearly overkill, and they are common.

If you only need to know how many processors a machine has, or whether it is big enough to run four workers, the answer is a sysconf call or reading a filesystem, and adding a topology library to a small project is a cost with no benefit. hwloc itself makes this point in the other direction: on an unsupported operating system it degrades to exactly that, reporting the number of processors and no topology.

The second case is when the platform is fixed and known. If you control the machine and it is a single socket, single NUMA node box, then locality is a solved problem and a topology library has nothing to discover.

The third is when you need only one fact. Whether two specific processors share a cache, or how much memory sits in a particular NUMA node, can often be answered by the platform's own tools, on Linux by reading the sysfs topology tree directly, and on other systems by the OS specific facilities. hwloc is the portable, structured answer to that question across seven operating system families, and the sysfs route is the local, Linux-only answer.

What hwloc adds over reading sysfs yourself is portability, a consistent object model, the cpuset bitmap API for placement, and the fake topology support for testing. If you are writing code that must run on Linux, AIX, Solaris and Windows, that combination is hard to reproduce, and the library has been doing it for two decades.

Editorial conclusion

Adopt hwloc if you are writing a scheduler, a runtime or an HPC application that needs to know where memory and cores sit relative to each other, since hand rolling that logic is a large and error prone job. Do not adopt it if you only need the processor count, because on unsupported operating systems hwloc reports the number of processors and no topology at all. Verify first that the platform you target is in the supported operating system list, that lstopo on your own machine shows the cache and NUMA information you expect, and that the LICENSE file terms suit how you plan to distribute your code.

Frequently asked questions

How do I check whether hwloc works on my machine?

The documentation says to just try to build it and run lstopo or lstopo-no-graphics. If something does not look right, such as bogus or missing cache information, the Questions and Bugs section of the documentation is where to look.

What does hwloc actually report about a machine?

A hierarchical map of key computing elements within a node: NUMA memory nodes, shared caches, processor packages, dies and cores, processing units or logical processors, and I/O devices, along with attributes such as cache and memory information.

Which operating systems does hwloc support?

Linux, Solaris, AIX, Darwin and OS X, FreeBSD and variants, NetBSD, and Microsoft Windows. On an unsupported operating system hwloc only reports the number of processors and no topology information is available.

Can I use hwloc to bind my application to specific cores?

Yes. Each hwloc object contains a cpuset describing the list of processing units, and the project provides a CPU bitmap API plus utility programs for binding processes, so applications can be bound onto particular cores or memory nodes.

Does hwloc offer a way to test code without real hardware?

Yes. For development and debugging, hwloc can work on fake topologies, either a symmetrical tree generated from a list of level arities, or a remote machine simulation through gathering topology as XML files.

What licence is hwloc released under?

A custom licence that GitHub cannot classify, with the terms in the LICENSE file at the root of the repository. The project is not archived and the last push was on 2026-10-15, with hwloc-2.14.0 released on 2026-06-09.

Official sources

  1. Issues
  2. open-mpi/hwloc on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/open-mpi-hwloc.svg)](https://hysenlabs.com/projects/open-mpi-hwloc)

Was this useful?