Arcane  v3.16.0.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-2022 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-2018 */
9/* */
10/* Gestion de l'affinité des processeurs via la bibiliothèque HWLOC. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/IProcessorAffinityService.h"
17#include "arcane/utils/ITraceMng.h"
18#include "arcane/utils/OStringStream.h"
19
20#include "arcane/FactoryService.h"
21#include "arcane/AbstractService.h"
22
23extern "C"
24{
25#include <hwloc.h>
26}
27
28#include <cstdio>
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33ARCANE_BEGIN_NAMESPACE
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38class HWLocProcessorAffinityService
39: public AbstractService
41{
42 public:
43
44 HWLocProcessorAffinityService(const ServiceBuildInfo& sbi)
45 : AbstractService(sbi) , m_is_init(false), m_topology(hwloc_topology_t())
46 {
47 }
48
49 //<! Libère les ressources
50 ~HWLocProcessorAffinityService() override
51 {
52 if (m_is_init)
53 hwloc_topology_destroy (m_topology);
54 }
55
56 public:
57
58 void build() override {}
59
60 public:
61
62 void printInfos() override;
63 String cpuSetString() override;
64 void bindThread(Int32 cpu) override;
65
66 Int32 numberOfCore() override;
67 Int32 numberOfSocket() override;
68 Int32 numberOfProcessingUnit() override;
69
70 private:
71
72 private:
73
74 bool m_is_init;
75 hwloc_topology_t m_topology;
76
77 private:
78
79 void _checkInit();
80 void _outputTopology(hwloc_obj_t l,hwloc_obj_t parent,
81 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.";
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 err = hwloc_topology_load (m_topology);
162 if (err!=0){
163 info() << "Error in hwloc_topology_load r=" << err;
164 return;
165 }
166
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
172String HWLocProcessorAffinityService::
173cpuSetString()
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
188void HWLocProcessorAffinityService::
189printInfos()
190{
191 _checkInit();
192 OStringStream ostrf;
193 _outputTopology (hwloc_get_root_obj(m_topology), NULL, 0,ostrf);
194 info() << ostrf.str();
195 info() << "Cpuset: " << cpuSetString();
196}
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
201void HWLocProcessorAffinityService::
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
235int 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 * \brief Returns the number of Processing Unit, or (Logical) Processor
248 * \return -1 on error
249 ******************************************************************************/
250
251int HWLocProcessorAffinityService::
252numberOfCore(void)
253{
254 return _numberOf(HWLOC_OBJ_CORE);
255}
256
257/******************************************************************************
258 * \brief Returns the number of Processing Unit, or (Logical) Processor
259 * \return -1 on error
260 ******************************************************************************/
261
262int HWLocProcessorAffinityService::
263numberOfSocket()
264{
265 return _numberOf(HWLOC_OBJ_SOCKET);
266}
267
268/******************************************************************************
269 * \brief Returns the number of Processing Unit, or (Logical) Processor
270 * \return -1 on error
271 ******************************************************************************/
272int HWLocProcessorAffinityService::
273numberOfProcessingUnit()
274{
275 return _numberOf(HWLOC_OBJ_PU);
276}
277
278/*---------------------------------------------------------------------------*/
279/*---------------------------------------------------------------------------*/
280
281ARCANE_REGISTER_APPLICATION_FACTORY(HWLocProcessorAffinityService,
282 IProcessorAffinityService,
283 HWLoc);
284
285/*---------------------------------------------------------------------------*/
286/*---------------------------------------------------------------------------*/
287
288ARCANE_END_NAMESPACE
289
290/*---------------------------------------------------------------------------*/
291/*---------------------------------------------------------------------------*/
#define ARCANE_REGISTER_APPLICATION_FACTORY(aclass, ainterface, aname)
Enregistre un service de fabrique pour la classe aclass.
AbstractService(const ServiceBuildInfo &)
Constructeur à partir d'un ServiceBuildInfo.
void build() override
Construction de niveau build du service.
Interface d'un service de de trace des appels de fonctions.
Flot de sortie lié à une String.
Structure contenant les informations pour créer un service.
Chaîne de caractères unicode.
Int32 Integer
Type représentant un entier.
std::int32_t Int32
Type entier signé sur 32 bits.