dispenso 1.6.0
A library for task parallelism
Loading...
Searching...
No Matches
cpu_set.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
26#pragma once
27
28#include <cstdint>
29#include <thread>
30#include <vector>
31
32#include <dispenso/platform.h>
33
34#if defined(__linux__) || defined(__FreeBSD__)
35#define DISPENSO_CPUSET_LINUXY
36#endif // linuxy
37
38#if defined(DISPENSO_CPUSET_LINUXY)
39#include <pthread.h>
40#include <sched.h>
41#elif defined(_WIN32)
42#define DISPENSO_CPUSET_WINDOWS
43#endif // supported os
44
45// Note: Windows uses SetThreadGroupAffinity for binding and
46// GetLogicalProcessorInformationEx for NUMA/cache topology, behind the same public API.
47//
48// macOS does not support explicit CPU pinning. bindCurrentThread() is a no-op and
49// returns false. Topology queries return a single-node fallback.
50//
51// FreeBSD binding support is present (cpuset_setaffinity uses a similar interface to
52// Linux), but topology detection requires test hardware and is deferred.
53
60#ifndef DISPENSO_MAX_GROUP_SIZE
61#define DISPENSO_MAX_GROUP_SIZE 16
62#endif
63
64namespace dispenso {
65
77constexpr int32_t kDefaultMaxGroupSize = DISPENSO_MAX_GROUP_SIZE;
78
84struct CacheGroup {
85 std::vector<int32_t> cpus;
86 int32_t cacheId;
87};
88
89// Forward declaration; full definition follows CpuSet (ThreadGroup has a CpuSet member).
90struct ThreadGroup;
91
139class CpuSet {
140 public:
144 DISPENSO_DLL_ACCESS CpuSet();
145
149 DISPENSO_DLL_ACCESS void clear();
150
155 DISPENSO_DLL_ACCESS void add(int32_t hardwareThread);
156
162 DISPENSO_DLL_ACCESS void addRange(int32_t start, int32_t end);
163
168 DISPENSO_DLL_ACCESS void remove(int32_t hardwareThread);
169
175 DISPENSO_DLL_ACCESS void removeRange(int32_t start, int32_t end);
176
182 DISPENSO_DLL_ACCESS bool contains(int32_t hardwareThread) const;
183
187 DISPENSO_DLL_ACCESS int32_t count() const;
188
197 DISPENSO_DLL_ACCESS bool bindCurrentThread() const;
198
205 DISPENSO_DLL_ACCESS static int32_t totalNumaNodes();
206
217 DISPENSO_DLL_ACCESS static int32_t currentHardwareThread();
218
235 static constexpr uint32_t kRefreshPeriod = 32;
236 static DISPENSO_THREAD_LOCAL int32_t cachedCpu = -1;
237 static DISPENSO_THREAD_LOCAL uint32_t counter = 0;
238 if ((counter++ & (kRefreshPeriod - 1)) == 0) {
239 cachedCpu = currentHardwareThread();
240 }
241 return cachedCpu;
242 }
243
249 DISPENSO_DLL_ACCESS static const CpuSet& node(int32_t numaNode);
250
258 DISPENSO_DLL_ACCESS static const CpuSet& all();
259
269 DISPENSO_DLL_ACCESS static int32_t availableCount();
270
283 DISPENSO_DLL_ACCESS static const std::vector<CacheGroup>& l2CacheGroups();
284
297 DISPENSO_DLL_ACCESS static const std::vector<CacheGroup>& l3CacheGroups();
298
327 DISPENSO_DLL_ACCESS static std::vector<ThreadGroup> buildThreadGroups(
328 int32_t maxGroupSize = kDefaultMaxGroupSize);
329
330 private:
331#if defined(DISPENSO_CPUSET_LINUXY)
332 cpu_set_t set_;
333#else
334 // Portable bitset supporting up to kMaxCpus logical processors.
335 // 1024 matches Linux cpu_set_t and covers all practical configurations.
336 // Windows Server 2025 supports up to 12,288 (192 groups x 64) but
337 // no known hardware approaches that limit. Can be increased later;
338 // dispenso does not guarantee ABI stability.
339 static constexpr int32_t kMaxCpus = 1024;
340 static constexpr int32_t kBitsPerWord = 64;
341 static constexpr int32_t kNumWords = kMaxCpus / kBitsPerWord;
342 uint64_t words_[kNumWords];
343#endif
344};
345
362 std::vector<int32_t> cpus;
364};
365
366namespace detail {
372DISPENSO_DLL_ACCESS CpuSet parseLinuxCpuList(const char* input);
373} // namespace detail
374
375} // namespace dispenso
A set of CPU IDs for affinity manipulation and topology queries.
Definition cpu_set.h:139
static int32_t currentHardwareThreadApprox()
Approximate CPU ID for the calling thread, refreshed periodically.
Definition cpu_set.h:234
static DISPENSO_DLL_ACCESS const std::vector< CacheGroup > & l3CacheGroups()
Returns the L3 cache sharing groups.
DISPENSO_DLL_ACCESS void add(int32_t hardwareThread)
Adds a single CPU to the set.
static DISPENSO_DLL_ACCESS const CpuSet & node(int32_t numaNode)
Returns the CPU set for a specific NUMA node.
DISPENSO_DLL_ACCESS bool contains(int32_t hardwareThread) const
Tests whether a CPU is in the set.
DISPENSO_DLL_ACCESS int32_t count() const
Returns the number of CPUs in the set.
DISPENSO_DLL_ACCESS void addRange(int32_t start, int32_t end)
Adds a range of CPUs to the set.
static DISPENSO_DLL_ACCESS int32_t availableCount()
Returns the number of hardware threads available to this process.
DISPENSO_DLL_ACCESS void clear()
Removes all CPUs from the set.
DISPENSO_DLL_ACCESS bool bindCurrentThread() const
Binds the calling thread to the CPUs in this set.
static DISPENSO_DLL_ACCESS std::vector< ThreadGroup > buildThreadGroups(int32_t maxGroupSize=kDefaultMaxGroupSize)
Builds scheduling thread groups from cache topology.
static DISPENSO_DLL_ACCESS int32_t totalNumaNodes()
Returns the total number of NUMA nodes detected.
static DISPENSO_DLL_ACCESS const CpuSet & all()
Returns a CPU set containing all online CPUs.
static DISPENSO_DLL_ACCESS int32_t currentHardwareThread()
Returns the CPU ID of the calling thread's current core.
static DISPENSO_DLL_ACCESS const std::vector< CacheGroup > & l2CacheGroups()
Returns the L2 cache sharing groups.
DISPENSO_DLL_ACCESS CpuSet()
Constructs an empty CPU set.
DISPENSO_DLL_ACCESS void removeRange(int32_t start, int32_t end)
Removes a range of CPUs from the set.
DISPENSO_DLL_ACCESS void remove(int32_t hardwareThread)
Removes a single CPU from the set.
Describes a group of CPUs that share a cache level.
Definition cpu_set.h:84
std::vector< int32_t > cpus
CPU IDs in this group.
Definition cpu_set.h:85
int32_t cacheId
Unique cache instance ID from sysfs.
Definition cpu_set.h:86
A scheduling group of CPUs for fork-join thread pool assignment.
Definition cpu_set.h:361
std::vector< int32_t > cpus
CPU IDs in this group (sorted)
Definition cpu_set.h:362
CpuSet affinityMask
Pre-built CpuSet for binding threads in this group.
Definition cpu_set.h:363