Arcane  v4.1.2.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
HWLocProcessorAffinity.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* HWLocProcessorAffinity.cc (C) 2000-2025 */
9/* */
10/* Gestion de l'affinité des processeurs via la bibiliothèque HWLOC. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/IProcessorAffinityService.h"
15#include "arcane/utils/ITraceMng.h"
16#include "arcane/utils/OStringStream.h"
17
18#include "arcane/core/FactoryService.h"
19#include "arcane/core/AbstractService.h"
20
21#include "arccore/base/internal/DependencyInjection.h"
22
23#include <hwloc.h>
24
25#include <cstdio>
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
30namespace Arcane
31{
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36class HWLocProcessorAffinityService
37: public TraceAccessor
39{
40 public:
41
42 explicit HWLocProcessorAffinityService(const ServiceBuildInfo& sbi)
44 {
45 }
46 explicit HWLocProcessorAffinityService(ITraceMng* tm)
47 : TraceAccessor(tm)
48 {
49 }
50
51 //<! Libère les ressources
52 ~HWLocProcessorAffinityService() override
53 {
54 if (m_topology)
55 hwloc_topology_destroy(m_topology);
56 }
57
58 public:
59
60 void build() override {}
61
62 public:
63
64 void printInfos() override;
65 String cpuSetString() override;
66 void bindThread(Int32 cpu) override;
67
68 Int32 numberOfCore() override;
69 Int32 numberOfSocket() override;
71
72 private:
73 private:
74
75 bool m_is_init = false;
76 hwloc_topology_t m_topology = nullptr;
77
78 private:
79
80 void _checkInit();
81 void _outputTopology(hwloc_obj_t l, hwloc_obj_t parent, int i, OStringStream& ostr);
82 int _numberOf(const hwloc_obj_type_t);
83};
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87// Recopie temporaire de 'hwloc_obj_snprintf' qui n'existe plus
88// à partir de la version 2.0 de hwloc
89static int
90_internal_hwloc_obj_snprintf(char* string, size_t size,
91 hwloc_obj* l, const char* _indexprefix, int verbose)
92{
93 const char* indexprefix = _indexprefix ? _indexprefix : "#";
94 char os_index[12] = "";
95 char type[64];
96 char attr[128];
97 int attrlen;
98
99 if (l->os_index != (unsigned)-1) {
100 std::snprintf(os_index, 12, "%s%u", indexprefix, l->os_index);
101 }
102
103 hwloc_obj_type_snprintf(type, sizeof(type), l, verbose);
104 attrlen = hwloc_obj_attr_snprintf(attr, sizeof(attr), l, " ", verbose);
105
106 if (attrlen > 0)
107 return std::snprintf(string, size, "%s%s(%s)", type, os_index, attr);
108 else
109 return std::snprintf(string, size, "%s%s", type, os_index);
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
115/* Recursively output topology in a console fashion */
116void HWLocProcessorAffinityService::
117_outputTopology(hwloc_obj_t l, hwloc_obj_t parent, int i, OStringStream& ostr)
118{
119 const char* indexprefix = "#";
120 char line[512];
121 if (parent && parent->arity == 1 && hwloc_bitmap_isequal(l->cpuset, parent->cpuset)) {
122 ostr() << " + ";
123 }
124 else {
125 if (parent) {
126 info() << ostr.str();
127 ostr.reset();
128 }
129 for (int z = 0; z < 2 * i; ++z)
130 ostr() << ' ';
131 i++;
132 }
133 _internal_hwloc_obj_snprintf(line, sizeof(line) - 1, l, indexprefix, 0);
134 ostr() << line;
135 unsigned int arity = l->arity;
136 if (arity != 0 || (!i && !arity)) {
137 for (unsigned int x = 0; x < arity; ++x) {
138 _outputTopology(l->children[x], l, i, ostr);
139 }
140 }
141}
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
145
146void HWLocProcessorAffinityService::
147_checkInit()
148{
149 if (m_is_init)
150 return;
151 m_is_init = true;
152
153 info() << "Getting hardware architecture hwloc_version=" << HWLOC_VERSION;
154 int err = hwloc_topology_init(&m_topology);
155 if (err != 0) {
156 info() << "Error in hwloc_topology_init r=" << err;
157 return;
158 }
159 unsigned long flags = 0;
160 hwloc_topology_set_flags(m_topology, flags);
161
162 err = hwloc_topology_load(m_topology);
163 if (err != 0) {
164 info() << "Error in hwloc_topology_load r=" << err;
165 return;
166 }
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
174{
175 hwloc_bitmap_t new_cpuset = hwloc_bitmap_alloc();
176 hwloc_get_cpubind(m_topology, new_cpuset, 0 | HWLOC_CPUBIND_THREAD);
177 char result_s[1024];
178 hwloc_bitmap_snprintf(result_s, sizeof(result_s) - 1, new_cpuset);
179 String s{ StringView(result_s) };
180 //ostr() << "R=" << result_s << '\n';
181 hwloc_bitmap_free(new_cpuset);
182 return s;
183}
184
185/*---------------------------------------------------------------------------*/
186/*---------------------------------------------------------------------------*/
187
190{
191 _checkInit();
192 OStringStream ostrf;
193 _outputTopology(hwloc_get_root_obj(m_topology), nullptr, 0, ostrf);
194 info() << ostrf.str();
195 info() << "Cpuset: " << cpuSetString();
196}
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
202bindThread(Int32 cpu)
203{
204 int flags = 0;
205 hwloc_bitmap_t new_cpuset = hwloc_bitmap_alloc();
206 hwloc_get_cpubind(m_topology, new_cpuset, 0 | HWLOC_CPUBIND_THREAD);
207
208 {
209 Integer cpu_index = 0;
210 unsigned int cpu_iter = 0;
211 hwloc_bitmap_foreach_begin(cpu_iter, new_cpuset)
212 {
213 //info() << "CPUSET ITER =" << cpu_iter << " wanted=" << cpu
214 // << " is_set?=" << hwloc_cpuset_isset(new_cpuset, cpu_iter);
215 if (cpu_index == cpu)
216 hwloc_bitmap_only(new_cpuset, cpu_iter);
217 ++cpu_index;
218 }
219 hwloc_bitmap_foreach_end();
220 }
221
222 hwloc_set_cpubind(m_topology, new_cpuset, flags | HWLOC_CPUBIND_THREAD);
223
224 // Regarde si bind ok
225 hwloc_get_cpubind(m_topology, new_cpuset, 0 | HWLOC_CPUBIND_THREAD);
226 char result_s[1024];
227 hwloc_bitmap_snprintf(result_s, sizeof(result_s) - 1, new_cpuset);
228 //info() << "CPUSET V2=" << result_s;
229 hwloc_bitmap_free(new_cpuset);
230}
231
232/*---------------------------------------------------------------------------*/
233/*---------------------------------------------------------------------------*/
234
235Int32 HWLocProcessorAffinityService::
236_numberOf(const hwloc_obj_type_t that)
237{
238 _checkInit();
239 int depth = hwloc_get_type_depth(m_topology, that);
240 if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
241 return -1;
242 int width = hwloc_get_nbobjs_by_depth(m_topology, depth);
243 return width;
244}
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
250numberOfCore(void)
251{
252 return _numberOf(HWLOC_OBJ_CORE);
253}
254
255/*---------------------------------------------------------------------------*/
256/*---------------------------------------------------------------------------*/
257
260{
261 return _numberOf(HWLOC_OBJ_SOCKET);
262}
263
264/*---------------------------------------------------------------------------*/
265/*---------------------------------------------------------------------------*/
266
269{
270 return _numberOf(HWLOC_OBJ_PU);
271}
272
273/*---------------------------------------------------------------------------*/
274/*---------------------------------------------------------------------------*/
275
278 HWLoc);
279
280/*---------------------------------------------------------------------------*/
281/*---------------------------------------------------------------------------*/
282
283ARCANE_DI_REGISTER_PROVIDER(HWLocProcessorAffinityService,
284 DependencyInjection::ProviderProperty("HWLoc"),
285 ARCANE_DI_INTERFACES(IProcessorAffinityService),
286 ARCANE_DI_CONSTRUCTOR(ITraceMng*));
287
288/*---------------------------------------------------------------------------*/
289/*---------------------------------------------------------------------------*/
290
291} // namespace Arcane
292
293/*---------------------------------------------------------------------------*/
294/*---------------------------------------------------------------------------*/
#define ARCANE_REGISTER_APPLICATION_FACTORY(aclass, ainterface, aname)
Enregistre un service de fabrique pour la classe aclass.
Int32 numberOfProcessingUnit() override
Nombre de coeurs logiques (-1 si inconnu)
void bindThread(Int32 cpu) override
Contraint le thread courant à rester sur le coeur d'indice cpu.
void printInfos() override
Affiche les informations complète de topologie via info()
Int32 numberOfCore() override
Nombre de coeurs CPU (-1 si inconnu)
String cpuSetString() override
Retourne le cpuset pour le thread courant.
Int32 numberOfSocket() override
Nombre de sockets (-1 si inconnu)
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
Interface d'un service de gestion de l'affinité des coeurs CPU.
Interface du gestionnaire de traces.
Flot de sortie lié à une String.
IApplication * application() const
Accès à l'application IApplication associé.
Structure contenant les informations pour créer un service.
Vue sur une chaîne de caractères UTF-8.
Definition StringView.h:47
Chaîne de caractères unicode.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage info() const
Flot pour un message d'information.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.
std::int32_t Int32
Type entier signé sur 32 bits.