memattrs.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /*
  2. * Copyright © 2019-2023 Inria. All rights reserved.
  3. * See COPYING in top-level directory.
  4. */
  5. /** \file
  6. * \brief Memory node attributes.
  7. */
  8. #ifndef HWLOC_MEMATTR_H
  9. #define HWLOC_MEMATTR_H
  10. #include "hwloc.h"
  11. #ifdef __cplusplus
  12. extern "C" {
  13. #elif 0
  14. }
  15. #endif
  16. /** \defgroup hwlocality_memattrs Comparing memory node attributes for finding where to allocate on
  17. *
  18. * Platforms with heterogeneous memory require ways to decide whether
  19. * a buffer should be allocated on "fast" memory (such as HBM),
  20. * "normal" memory (DDR) or even "slow" but large-capacity memory
  21. * (non-volatile memory).
  22. * These memory nodes are called "Targets" while the CPU accessing them
  23. * is called the "Initiator". Access performance depends on their
  24. * locality (NUMA platforms) as well as the intrinsic performance
  25. * of the targets (heterogeneous platforms).
  26. *
  27. * The following attributes describe the performance of memory accesses
  28. * from an Initiator to a memory Target, for instance their latency
  29. * or bandwidth.
  30. * Initiators performing these memory accesses are usually some PUs or Cores
  31. * (described as a CPU set).
  32. * Hence a Core may choose where to allocate a memory buffer by comparing
  33. * the attributes of different target memory nodes nearby.
  34. *
  35. * There are also some attributes that are system-wide.
  36. * Their value does not depend on a specific initiator performing
  37. * an access.
  38. * The memory node Capacity is an example of such attribute without
  39. * initiator.
  40. *
  41. * One way to use this API is to start with a cpuset describing the Cores where
  42. * a program is bound. The best target NUMA node for allocating memory in this
  43. * program on these Cores may be obtained by passing this cpuset as an initiator
  44. * to hwloc_memattr_get_best_target() with the relevant memory attribute.
  45. * For instance, if the code is latency limited, use the Latency attribute.
  46. *
  47. * A more flexible approach consists in getting the list of local NUMA nodes
  48. * by passing this cpuset to hwloc_get_local_numanode_objs().
  49. * Attribute values for these nodes, if any, may then be obtained with
  50. * hwloc_memattr_get_value() and manually compared with the desired criteria.
  51. *
  52. * \sa An example is available in doc/examples/memory-attributes.c in the source tree.
  53. *
  54. * \note The API also supports specific objects as initiator,
  55. * but it is currently not used internally by hwloc.
  56. * Users may for instance use it to provide custom performance
  57. * values for host memory accesses performed by GPUs.
  58. *
  59. * \note The interface actually also accepts targets that are not NUMA nodes.
  60. * @{
  61. */
  62. /** \brief Memory node attributes. */
  63. enum hwloc_memattr_id_e {
  64. /** \brief
  65. * The \"Capacity\" is returned in bytes (local_memory attribute in objects).
  66. *
  67. * Best capacity nodes are nodes with <b>higher capacity</b>.
  68. *
  69. * No initiator is involved when looking at this attribute.
  70. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST.
  71. * \hideinitializer
  72. */
  73. HWLOC_MEMATTR_ID_CAPACITY = 0,
  74. /** \brief
  75. * The \"Locality\" is returned as the number of PUs in that locality
  76. * (e.g. the weight of its cpuset).
  77. *
  78. * Best locality nodes are nodes with <b>smaller locality</b>
  79. * (nodes that are local to very few PUs).
  80. * Poor locality nodes are nodes with larger locality
  81. * (nodes that are local to the entire machine).
  82. *
  83. * No initiator is involved when looking at this attribute.
  84. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST.
  85. * \hideinitializer
  86. */
  87. HWLOC_MEMATTR_ID_LOCALITY = 1,
  88. /** \brief
  89. * The \"Bandwidth\" is returned in MiB/s, as seen from the given initiator location.
  90. *
  91. * Best bandwidth nodes are nodes with <b>higher bandwidth</b>.
  92. *
  93. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST
  94. * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
  95. *
  96. * This is the average bandwidth for read and write accesses. If the platform
  97. * provides individual read and write bandwidths but no explicit average value,
  98. * hwloc computes and returns the average.
  99. * \hideinitializer
  100. */
  101. HWLOC_MEMATTR_ID_BANDWIDTH = 2,
  102. /** \brief
  103. * The \"ReadBandwidth\" is returned in MiB/s, as seen from the given initiator location.
  104. *
  105. * Best bandwidth nodes are nodes with <b>higher bandwidth</b>.
  106. *
  107. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST
  108. * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
  109. * \hideinitializer
  110. */
  111. HWLOC_MEMATTR_ID_READ_BANDWIDTH = 4,
  112. /** \brief
  113. * The \"WriteBandwidth\" is returned in MiB/s, as seen from the given initiator location.
  114. *
  115. * Best bandwidth nodes are nodes with <b>higher bandwidth</b>.
  116. *
  117. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST
  118. * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
  119. * \hideinitializer
  120. */
  121. HWLOC_MEMATTR_ID_WRITE_BANDWIDTH = 5,
  122. /** \brief
  123. * The \"Latency\" is returned as nanoseconds, as seen from the given initiator location.
  124. *
  125. * Best latency nodes are nodes with <b>smaller latency</b>.
  126. *
  127. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_LOWER_FIRST
  128. * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
  129. *
  130. * This is the average latency for read and write accesses. If the platform
  131. * provides individual read and write latencies but no explicit average value,
  132. * hwloc computes and returns the average.
  133. * \hideinitializer
  134. */
  135. HWLOC_MEMATTR_ID_LATENCY = 3,
  136. /** \brief
  137. * The \"ReadLatency\" is returned as nanoseconds, as seen from the given initiator location.
  138. *
  139. * Best latency nodes are nodes with <b>smaller latency</b>.
  140. *
  141. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_LOWER_FIRST
  142. * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
  143. * \hideinitializer
  144. */
  145. HWLOC_MEMATTR_ID_READ_LATENCY = 6,
  146. /** \brief
  147. * The \"WriteLatency\" is returned as nanoseconds, as seen from the given initiator location.
  148. *
  149. * Best latency nodes are nodes with <b>smaller latency</b>.
  150. *
  151. * The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_LOWER_FIRST
  152. * and ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR.
  153. * \hideinitializer
  154. */
  155. HWLOC_MEMATTR_ID_WRITE_LATENCY = 7,
  156. /* TODO persistence? */
  157. HWLOC_MEMATTR_ID_MAX /**< \private Sentinel value */
  158. };
  159. /** \brief A memory attribute identifier.
  160. * May be either one of ::hwloc_memattr_id_e or a new id returned by hwloc_memattr_register().
  161. */
  162. typedef unsigned hwloc_memattr_id_t;
  163. /** \brief Return the identifier of the memory attribute with the given name.
  164. *
  165. * \return 0 on success.
  166. * \return -1 with errno set to \c EINVAL if no such attribute exists.
  167. */
  168. HWLOC_DECLSPEC int
  169. hwloc_memattr_get_by_name(hwloc_topology_t topology,
  170. const char *name,
  171. hwloc_memattr_id_t *id);
  172. /** \brief Type of location. */
  173. enum hwloc_location_type_e {
  174. /** \brief Location is given as a cpuset, in the location cpuset union field. \hideinitializer */
  175. HWLOC_LOCATION_TYPE_CPUSET = 1,
  176. /** \brief Location is given as an object, in the location object union field. \hideinitializer */
  177. HWLOC_LOCATION_TYPE_OBJECT = 0
  178. };
  179. /** \brief Where to measure attributes from. */
  180. struct hwloc_location {
  181. /** \brief Type of location. */
  182. enum hwloc_location_type_e type;
  183. /** \brief Actual location. */
  184. union hwloc_location_u {
  185. /** \brief Location as a cpuset, when the location type is ::HWLOC_LOCATION_TYPE_CPUSET. */
  186. hwloc_cpuset_t cpuset;
  187. /** \brief Location as an object, when the location type is ::HWLOC_LOCATION_TYPE_OBJECT. */
  188. hwloc_obj_t object;
  189. } location;
  190. };
  191. /** \brief Flags for selecting target NUMA nodes. */
  192. enum hwloc_local_numanode_flag_e {
  193. /** \brief Select NUMA nodes whose locality is larger than the given cpuset.
  194. * For instance, if a single PU (or its cpuset) is given in \p initiator,
  195. * select all nodes close to the package that contains this PU.
  196. * \hideinitializer
  197. */
  198. HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY = (1UL<<0),
  199. /** \brief Select NUMA nodes whose locality is smaller than the given cpuset.
  200. * For instance, if a package (or its cpuset) is given in \p initiator,
  201. * also select nodes that are attached to only a half of that package.
  202. * \hideinitializer
  203. */
  204. HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY = (1UL<<1),
  205. /** \brief Select all NUMA nodes in the topology.
  206. * The initiator \p initiator is ignored.
  207. * \hideinitializer
  208. */
  209. HWLOC_LOCAL_NUMANODE_FLAG_ALL = (1UL<<2)
  210. };
  211. /** \brief Return an array of local NUMA nodes.
  212. *
  213. * By default only select the NUMA nodes whose locality is exactly
  214. * the given \p location. More nodes may be selected if additional flags
  215. * are given as a OR'ed set of ::hwloc_local_numanode_flag_e.
  216. *
  217. * If \p location is given as an explicit object, its CPU set is used
  218. * to find NUMA nodes with the corresponding locality.
  219. * If the object does not have a CPU set (e.g. I/O object), the CPU
  220. * parent (where the I/O object is attached) is used.
  221. *
  222. * On input, \p nr points to the number of nodes that may be stored
  223. * in the \p nodes array.
  224. * On output, \p nr will be changed to the number of stored nodes,
  225. * or the number of nodes that would have been stored if there were
  226. * enough room.
  227. *
  228. * \return 0 on success or -1 on error.
  229. *
  230. * \note Some of these NUMA nodes may not have any memory attribute
  231. * values and hence not be reported as actual targets in other functions.
  232. *
  233. * \note The number of NUMA nodes in the topology (obtained by
  234. * hwloc_bitmap_weight() on the root object nodeset) may be used
  235. * to allocate the \p nodes array.
  236. *
  237. * \note When an object CPU set is given as locality, for instance a Package,
  238. * and when flags contain both ::HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY
  239. * and ::HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY,
  240. * the returned array corresponds to the nodeset of that object.
  241. */
  242. HWLOC_DECLSPEC int
  243. hwloc_get_local_numanode_objs(hwloc_topology_t topology,
  244. struct hwloc_location *location,
  245. unsigned *nr,
  246. hwloc_obj_t *nodes,
  247. unsigned long flags);
  248. /** \brief Return an attribute value for a specific target NUMA node.
  249. *
  250. * If the attribute does not relate to a specific initiator
  251. * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
  252. * location \p initiator is ignored and may be \c NULL.
  253. *
  254. * \p flags must be \c 0 for now.
  255. *
  256. * \return 0 on success.
  257. * \return -1 on error, for instance with errno set to \c EINVAL if flags
  258. * are invalid or no such attribute exists.
  259. *
  260. * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
  261. * when refering to accesses performed by CPU cores.
  262. * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
  263. * but users may for instance use it to provide custom information about
  264. * host memory accesses performed by GPUs.
  265. */
  266. HWLOC_DECLSPEC int
  267. hwloc_memattr_get_value(hwloc_topology_t topology,
  268. hwloc_memattr_id_t attribute,
  269. hwloc_obj_t target_node,
  270. struct hwloc_location *initiator,
  271. unsigned long flags,
  272. hwloc_uint64_t *value);
  273. /** \brief Return the best target NUMA node for the given attribute and initiator.
  274. *
  275. * If the attribute does not relate to a specific initiator
  276. * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
  277. * location \p initiator is ignored and may be \c NULL.
  278. *
  279. * If \p value is non \c NULL, the corresponding value is returned there.
  280. *
  281. * If multiple targets have the same attribute values, only one is
  282. * returned (and there is no way to clarify how that one is chosen).
  283. * Applications that want to detect targets with identical/similar
  284. * values, or that want to look at values for multiple attributes,
  285. * should rather get all values using hwloc_memattr_get_value()
  286. * and manually select the target they consider the best.
  287. *
  288. * \p flags must be \c 0 for now.
  289. *
  290. * \return 0 on success.
  291. * \return -1 with errno set to \c ENOENT if there are no matching targets.
  292. * \return -1 with errno set to \c EINVAL if flags are invalid,
  293. * or no such attribute exists.
  294. *
  295. * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
  296. * when refering to accesses performed by CPU cores.
  297. * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
  298. * but users may for instance use it to provide custom information about
  299. * host memory accesses performed by GPUs.
  300. */
  301. HWLOC_DECLSPEC int
  302. hwloc_memattr_get_best_target(hwloc_topology_t topology,
  303. hwloc_memattr_id_t attribute,
  304. struct hwloc_location *initiator,
  305. unsigned long flags,
  306. hwloc_obj_t *best_target, hwloc_uint64_t *value);
  307. /** \brief Return the best initiator for the given attribute and target NUMA node.
  308. *
  309. * If \p value is non \c NULL, the corresponding value is returned there.
  310. *
  311. * If multiple initiators have the same attribute values, only one is
  312. * returned (and there is no way to clarify how that one is chosen).
  313. * Applications that want to detect initiators with identical/similar
  314. * values, or that want to look at values for multiple attributes,
  315. * should rather get all values using hwloc_memattr_get_value()
  316. * and manually select the initiator they consider the best.
  317. *
  318. * The returned initiator should not be modified or freed,
  319. * it belongs to the topology.
  320. *
  321. * \p flags must be \c 0 for now.
  322. *
  323. * \return 0 on success.
  324. * \return -1 with errno set to \c ENOENT if there are no matching initiators.
  325. * \return -1 with errno set to \c EINVAL if the attribute does not relate to a specific initiator
  326. * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR).
  327. */
  328. HWLOC_DECLSPEC int
  329. hwloc_memattr_get_best_initiator(hwloc_topology_t topology,
  330. hwloc_memattr_id_t attribute,
  331. hwloc_obj_t target,
  332. unsigned long flags,
  333. struct hwloc_location *best_initiator, hwloc_uint64_t *value);
  334. /** @} */
  335. /** \defgroup hwlocality_memattrs_manage Managing memory attributes
  336. * @{
  337. */
  338. /** \brief Return the name of a memory attribute.
  339. *
  340. * \return 0 on success.
  341. * \return -1 with errno set to \c EINVAL if the attribute does not exist.
  342. */
  343. HWLOC_DECLSPEC int
  344. hwloc_memattr_get_name(hwloc_topology_t topology,
  345. hwloc_memattr_id_t attribute,
  346. const char **name);
  347. /** \brief Return the flags of the given attribute.
  348. *
  349. * Flags are a OR'ed set of ::hwloc_memattr_flag_e.
  350. *
  351. * \return 0 on success.
  352. * \return -1 with errno set to \c EINVAL if the attribute does not exist.
  353. */
  354. HWLOC_DECLSPEC int
  355. hwloc_memattr_get_flags(hwloc_topology_t topology,
  356. hwloc_memattr_id_t attribute,
  357. unsigned long *flags);
  358. /** \brief Memory attribute flags.
  359. * Given to hwloc_memattr_register() and returned by hwloc_memattr_get_flags().
  360. */
  361. enum hwloc_memattr_flag_e {
  362. /** \brief The best nodes for this memory attribute are those with the higher values.
  363. * For instance Bandwidth.
  364. */
  365. HWLOC_MEMATTR_FLAG_HIGHER_FIRST = (1UL<<0),
  366. /** \brief The best nodes for this memory attribute are those with the lower values.
  367. * For instance Latency.
  368. */
  369. HWLOC_MEMATTR_FLAG_LOWER_FIRST = (1UL<<1),
  370. /** \brief The value returned for this memory attribute depends on the given initiator.
  371. * For instance Bandwidth and Latency, but not Capacity.
  372. */
  373. HWLOC_MEMATTR_FLAG_NEED_INITIATOR = (1UL<<2)
  374. };
  375. /** \brief Register a new memory attribute.
  376. *
  377. * Add a specific memory attribute that is not defined in ::hwloc_memattr_id_e.
  378. * Flags are a OR'ed set of ::hwloc_memattr_flag_e. It must contain at least
  379. * one of ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST or ::HWLOC_MEMATTR_FLAG_LOWER_FIRST.
  380. *
  381. * \return 0 on success.
  382. * \return -1 with errno set to \c EBUSY if another attribute already uses this name.
  383. */
  384. HWLOC_DECLSPEC int
  385. hwloc_memattr_register(hwloc_topology_t topology,
  386. const char *name,
  387. unsigned long flags,
  388. hwloc_memattr_id_t *id);
  389. /** \brief Set an attribute value for a specific target NUMA node.
  390. *
  391. * If the attribute does not relate to a specific initiator
  392. * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
  393. * location \p initiator is ignored and may be \c NULL.
  394. *
  395. * The initiator will be copied into the topology,
  396. * the caller should free anything allocated to store the initiator,
  397. * for instance the cpuset.
  398. *
  399. * \p flags must be \c 0 for now.
  400. *
  401. * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
  402. * when referring to accesses performed by CPU cores.
  403. * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
  404. * but users may for instance use it to provide custom information about
  405. * host memory accesses performed by GPUs.
  406. *
  407. * \return 0 on success or -1 on error.
  408. */
  409. HWLOC_DECLSPEC int
  410. hwloc_memattr_set_value(hwloc_topology_t topology,
  411. hwloc_memattr_id_t attribute,
  412. hwloc_obj_t target_node,
  413. struct hwloc_location *initiator,
  414. unsigned long flags,
  415. hwloc_uint64_t value);
  416. /** \brief Return the target NUMA nodes that have some values for a given attribute.
  417. *
  418. * Return targets for the given attribute in the \p targets array
  419. * (for the given initiator if any).
  420. * If \p values is not \c NULL, the corresponding attribute values
  421. * are stored in the array it points to.
  422. *
  423. * On input, \p nr points to the number of targets that may be stored
  424. * in the array \p targets (and \p values).
  425. * On output, \p nr points to the number of targets (and values) that
  426. * were actually found, even if some of them couldn't be stored in the array.
  427. * Targets that couldn't be stored are ignored, but the function still
  428. * returns success (\c 0). The caller may find out by comparing the value pointed
  429. * by \p nr before and after the function call.
  430. *
  431. * The returned targets should not be modified or freed,
  432. * they belong to the topology.
  433. *
  434. * Argument \p initiator is ignored if the attribute does not relate to a specific
  435. * initiator (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR).
  436. * Otherwise \p initiator may be non \c NULL to report only targets
  437. * that have a value for that initiator.
  438. *
  439. * \p flags must be \c 0 for now.
  440. *
  441. * \note This function is meant for tools and debugging (listing internal information)
  442. * rather than for application queries. Applications should rather select useful
  443. * NUMA nodes with hwloc_get_local_numanode_objs() and then look at their attribute
  444. * values.
  445. *
  446. * \return 0 on success or -1 on error.
  447. *
  448. * \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
  449. * when referring to accesses performed by CPU cores.
  450. * ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
  451. * but users may for instance use it to provide custom information about
  452. * host memory accesses performed by GPUs.
  453. */
  454. HWLOC_DECLSPEC int
  455. hwloc_memattr_get_targets(hwloc_topology_t topology,
  456. hwloc_memattr_id_t attribute,
  457. struct hwloc_location *initiator,
  458. unsigned long flags,
  459. unsigned *nr, hwloc_obj_t *targets, hwloc_uint64_t *values);
  460. /** \brief Return the initiators that have values for a given attribute for a specific target NUMA node.
  461. *
  462. * Return initiators for the given attribute and target node in the
  463. * \p initiators array.
  464. * If \p values is not \c NULL, the corresponding attribute values
  465. * are stored in the array it points to.
  466. *
  467. * On input, \p nr points to the number of initiators that may be stored
  468. * in the array \p initiators (and \p values).
  469. * On output, \p nr points to the number of initiators (and values) that
  470. * were actually found, even if some of them couldn't be stored in the array.
  471. * Initiators that couldn't be stored are ignored, but the function still
  472. * returns success (\c 0). The caller may find out by comparing the value pointed
  473. * by \p nr before and after the function call.
  474. *
  475. * The returned initiators should not be modified or freed,
  476. * they belong to the topology.
  477. *
  478. * \p flags must be \c 0 for now.
  479. *
  480. * If the attribute does not relate to a specific initiator
  481. * (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
  482. * no initiator is returned.
  483. *
  484. * \return 0 on success or -1 on error.
  485. *
  486. * \note This function is meant for tools and debugging (listing internal information)
  487. * rather than for application queries. Applications should rather select useful
  488. * NUMA nodes with hwloc_get_local_numanode_objs() and then look at their attribute
  489. * values for some relevant initiators.
  490. */
  491. HWLOC_DECLSPEC int
  492. hwloc_memattr_get_initiators(hwloc_topology_t topology,
  493. hwloc_memattr_id_t attribute,
  494. hwloc_obj_t target_node,
  495. unsigned long flags,
  496. unsigned *nr, struct hwloc_location *initiators, hwloc_uint64_t *values);
  497. /** @} */
  498. #ifdef __cplusplus
  499. } /* extern "C" */
  500. #endif
  501. #endif /* HWLOC_MEMATTR_H */