126 topo.
cpu_count = std::thread::hardware_concurrency();
135# ifndef THREADSCHEDULE_WINDOWS_VISTA_COMPAT
136 using get_active_processor_group_count_fn = WORD(WINAPI*)();
137 using get_active_processor_count_fn = DWORD(WINAPI*)(WORD);
139 HMODULE
const kernel32 = GetModuleHandleW(L
"kernel32.dll");
142 auto const get_group_count =
reinterpret_cast<get_active_processor_group_count_fn
>(
143 reinterpret_cast<void*
>(GetProcAddress(kernel32,
"GetActiveProcessorGroupCount")));
144 auto const get_processor_count =
reinterpret_cast<get_active_processor_count_fn
>(
145 reinterpret_cast<void*
>(GetProcAddress(kernel32,
"GetActiveProcessorCount")));
146 if (get_group_count && get_processor_count)
148 WORD
const group_count = get_group_count();
149 for (WORD group = 0; group < group_count; ++group)
151 DWORD
const processor_count = get_processor_count(group);
152 if (processor_count == 0)
154 topo.
cpu_count +=
static_cast<std::size_t
>(processor_count);
155 for (DWORD index = 0; index < processor_count; ++index)
156 topo.
node_to_cpus[0].emplace_back(
static_cast<int>(group) * 64 +
static_cast<int>(index));
164 SYSTEM_INFO system_info{};
165 GetSystemInfo(&system_info);
166 DWORD
const processor_count = system_info.dwNumberOfProcessors > 0 ? system_info.dwNumberOfProcessors : 1;
167 topo.
cpu_count =
static_cast<std::size_t
>(processor_count);
168 for (DWORD index = 0; index < processor_count; ++index)
169 topo.
node_to_cpus[0].emplace_back(
static_cast<int>(index));
173 if (node_ids.empty())
176 for (
int const node_id : node_ids)
178 auto const cpu_indices
180 if (cpu_indices.empty())
182 std::vector<cpu_id> cpus;
183 cpus.reserve(cpu_indices.size());
184 for (
int const cpu : cpu_indices)
185 cpus.emplace_back(cpu);
192 for (std::size_t i = 0; i < topo.
cpu_count; ++i)
193 topo.
node_to_cpus[0].emplace_back(
static_cast<std::int64_t
>(i));
213 auto const available_nodes = (std::min)(topo.numa_nodes, topo.node_to_cpus.size());
214 if (available_nodes == 0 || threads_per_node <= 0)
216 auto const wrapped_index = [](
int value, std::size_t count)
219 return static_cast<std::size_t
>(value) % count;
220 auto const magnitude =
static_cast<std::uint64_t
>(-(
static_cast<std::int64_t
>(value) + 1)) + 1;
221 auto const remainder =
static_cast<std::size_t
>(magnitude % count);
222 return remainder == 0 ? std::size_t{ 0 } : count - remainder;
224 auto const n = wrapped_index(node_index, available_nodes);
225 auto const& cpus = topo.node_to_cpus[n];
230 auto const cpu_count = cpus.size();
231 auto const first = wrapped_index(thread_index, cpu_count);
232 cpu_id const cpu = cpus[first];
234 for (
int k = 1; k < threads_per_node; ++k)
236 cpu_id const extra = cpus[(first +
static_cast<std::size_t
>(k)) % cpu_count];
auto affinity_for_node(cpu_topology const &topo, int node_index, int thread_index, int threads_per_node=1) -> thread_affinity
Build a thread_affinity for the given NUMA node using a pre-read topology.