Struct hwlocality::topology::editor::TopologyEditor
source · pub struct TopologyEditor<'topology>(/* private fields */);
hwloc-2_3_0
only.Expand description
Proxy for modifying a Topology
This proxy object is carefully crafted to only allow operations that are safe while modifying a topology and minimize the number of times the hwloc lazy caches will need to be refreshed.
The API is broken down into sections roughly following the structure of the upstream hwloc documentation:
Implementations§
source§impl TopologyEditor<'_>
impl TopologyEditor<'_>
§Kinds of CPU cores
sourcepub fn register_cpu_kind<'infos>(
&mut self,
cpuset: impl Deref<Target = CpuSet>,
forced_efficiency: Option<CpuEfficiency>,
infos: impl IntoIterator<Item = (&'infos str, &'infos str)>,
) -> Result<(), RegisterError>
Available on crate feature hwloc-2_4_0
only.
pub fn register_cpu_kind<'infos>( &mut self, cpuset: impl Deref<Target = CpuSet>, forced_efficiency: Option<CpuEfficiency>, infos: impl IntoIterator<Item = (&'infos str, &'infos str)>, ) -> Result<(), RegisterError>
hwloc-2_4_0
only.Register a kind of CPU in the topology.
Mark the PUs listed in cpuset
as being of the same kind with respect
to the given attributes.
cpuset
can be a &'_ CpuSet
or a BitmapRef<'_, CpuSet>
.
forced_efficiency
should be None
if unknown. Otherwise it is an
abstracted efficiency value to enforce the ranking of all kinds if all
of them have valid (and different) efficiencies.
Note that the efficiency reported later by Topology::cpu_kinds()
may
differ because hwloc will scale efficiency values down to between 0 and
the number of kinds minus 1.
If cpuset
overlaps with some existing kinds, those might get modified
or split. For instance if existing kind A contains PUs 0 and 1, and one
registers another kind for PU 1 and 2, there will be 3 resulting kinds:
existing kind A is restricted to only PU 0; new kind B contains only PU
1 and combines information from A and from the newly-registered kind;
new kind C contains only PU 2 and only gets information from the
newly-registered kind.
§Errors
ExcessiveEfficiency
ifforced_efficiency
exceeds hwloc’sc_int::MAX
limit.InfoContainsNul
if a provided info’s key or value contains NUL charsTooManyInfos
if the number of specified (key, value) info tuples exceeds hwloc’sc_uint::MAX
limit.
source§impl<'topology> TopologyEditor<'topology>
impl<'topology> TopologyEditor<'topology>
§Managing memory attributes
sourcepub fn register_memory_attribute(
&mut self,
name: &str,
flags: MemoryAttributeFlags,
) -> Result<MemoryAttributeBuilder<'_, 'topology>, RegisterError>
pub fn register_memory_attribute( &mut self, name: &str, flags: MemoryAttributeFlags, ) -> Result<MemoryAttributeBuilder<'_, 'topology>, RegisterError>
Register a new memory attribute
§Errors
BadFlags
ifflags
does not contain exactly one of theHIGHER_IS_BEST
andLOWER_IS_BEST
flags.NameContainsNul
ifname
contains NUL chars.NameTaken
if another attribute calledname
already exists.
source§impl TopologyEditor<'_>
impl TopologyEditor<'_>
§Add distances between objects
sourcepub fn add_distances(
&mut self,
name: Option<&str>,
kind: DistancesKind,
flags: AddDistancesFlags,
collect_objects_and_distances: impl FnOnce(&Topology) -> (Vec<Option<&TopologyObject>>, Vec<u64>),
) -> Result<(), HybridError<AddDistancesError>>
Available on crate feature hwloc-2_5_0
only.
pub fn add_distances( &mut self, name: Option<&str>, kind: DistancesKind, flags: AddDistancesFlags, collect_objects_and_distances: impl FnOnce(&Topology) -> (Vec<Option<&TopologyObject>>, Vec<u64>), ) -> Result<(), HybridError<AddDistancesError>>
hwloc-2_5_0
only.Create a new object distances matrix
kind
specifies the kind of distance. You should not use the
HETEROGENEOUS_TYPES
kind here, it will be set automatically.
flags
can be used to request the grouping of existing objects based on
distance.
The collect_objects_and_distances
callback should query the geometry
to collect references to the objects of interest, and produce the
corresponding distance matrix. If there are N output objects, then there
should be N.pow(2) output distances.
Distances must be provided in sender-major order: the distance from object 0 to object 1, then object 0 to object 2, … all the way to object N, and then from object 1 to object 0, and so on.
§Errors
InconsistentData
if the number of distances returned by the callback is not compatible with the number of objects (it should be the square of it)BadKind
if the providedkind
containsHETEROGENEOUS_TYPES
or several of the “FROM_” and “MEANS_” kindsBadObjectsCount
if less than 2 or more thanc_uint::MAX
objects are returned by the callback(hwloc does not support such configurations)ForeignEndpoint
if the callback returned objects that do not belong to this topologyNameContainsNul
if the providedname
contains NUL chars
source§impl TopologyEditor<'_>
impl TopologyEditor<'_>
§Remove distances between objects
sourcepub fn remove_distances(
&mut self,
find_distances: impl FnOnce(&Topology) -> Distances<'_>,
) -> Result<(), RawHwlocError>
pub fn remove_distances( &mut self, find_distances: impl FnOnce(&Topology) -> Distances<'_>, ) -> Result<(), RawHwlocError>
Remove a single distances matrix from the topology
The distances matrix to be removed can be selected using the
find_distances
callback.
sourcepub fn remove_all_distances(&mut self) -> Result<(), RawHwlocError>
pub fn remove_all_distances(&mut self) -> Result<(), RawHwlocError>
Remove all distance matrices from a topology
If these distances were used to group objects, these additional Group objects are not removed from the topology.
sourcepub fn remove_distances_at_depth<DepthLike>(
&mut self,
depth: DepthLike,
) -> Result<(), RawHwlocError>
pub fn remove_distances_at_depth<DepthLike>( &mut self, depth: DepthLike, ) -> Result<(), RawHwlocError>
Remove distance matrices for objects at a specific depth in the topology (if any)
Identical to remove_all_distances()
, but only applies to one level
of the topology.
depth
can be a Depth
, a NormalDepth
or an usize
.
sourcepub fn remove_distances_with_type(
&mut self,
ty: ObjectType,
) -> Result<(), RawHwlocError>
pub fn remove_distances_with_type( &mut self, ty: ObjectType, ) -> Result<(), RawHwlocError>
Remove distance matrices for objects of a specific type in the topology
Identical to remove_all_distances()
, but only applies to one level
of the topology.
source§impl<'topology> TopologyEditor<'topology>
impl<'topology> TopologyEditor<'topology>
§General-purpose utilities
source§impl<'topology> TopologyEditor<'topology>
impl<'topology> TopologyEditor<'topology>
§Basic modifications
sourcepub fn restrict<Set: SpecializedBitmap>(
&mut self,
set: &Set,
flags: RestrictFlags,
) -> Result<(), ParameterError<Set::Owned>>
pub fn restrict<Set: SpecializedBitmap>( &mut self, set: &Set, flags: RestrictFlags, ) -> Result<(), ParameterError<Set::Owned>>
Restrict the topology to the given CPU set or nodeset
The topology is modified so as to remove all objects that are not
included (or partially included) in the specified CpuSet
or
NodeSet
set. All objects CPU and node sets are restricted
accordingly.
Restricting the topology removes some locality information, hence the remaining objects may get reordered (including PUs and NUMA nodes), and their logical indices may change.
This call may not be reverted by restricting back to a larger set. Once
dropped during restriction, objects may not be brought back, except by
loading another topology with Topology::new()
or TopologyBuilder
.
§Errors
It is an error to attempt to remove all CPUs or NUMA nodes from a
topology using a set
that has no intersection with the relevant
topology set. The topology will not be modified in this case, and a
ParameterError
will be returned instead.
§Aborts
Failure to allocate internal data will lead to a process abort, because the topology gets corrupted in this case and must not be touched again, but we have no way to prevent this in a safe API.
sourcepub fn allow(
&mut self,
allow_set: AllowSet<'_>,
) -> Result<(), HybridError<AllowSetError>>
pub fn allow( &mut self, allow_set: AllowSet<'_>, ) -> Result<(), HybridError<AllowSetError>>
Change the sets of allowed PUs and NUMA nodes in the topology
This function only works if BuildFlags::INCLUDE_DISALLOWED
was set
during topology building. It does not modify any object, it only changes
the sets returned by Topology::allowed_cpuset()
and
Topology::allowed_nodeset()
.
It is notably useful when importing a topology from another process running in a different Linux Cgroup.
Removing objects from a topology should rather be performed with
TopologyEditor::restrict()
.
§Errors
EmptyCustom
if anAllowSet::Custom
does not do anything because both itscpuset
andnodeset
members are empty.InvalidCpuset
if applying thecpuset
of anAllowSet::Custom
would amount to disallowing all CPUs from the topology.InvalidNodeset
if applying thenodeset
of anAllowSet::Custom
would amount to disallowing all NUMA nodes from the topology.Unsupported
if the specifiedAllowSet
is not supported by the host operating system.
sourcepub fn insert_group_object<NormalFilter, MemoryFilter>(
&mut self,
dont_merge: bool,
find_parent: impl FnOnce(&Topology) -> &TopologyObject,
child_filter: GroupChildFilter<NormalFilter, MemoryFilter>,
) -> Result<InsertedGroup<'topology>, HybridError<InsertGroupError>>
pub fn insert_group_object<NormalFilter, MemoryFilter>( &mut self, dont_merge: bool, find_parent: impl FnOnce(&Topology) -> &TopologyObject, child_filter: GroupChildFilter<NormalFilter, MemoryFilter>, ) -> Result<InsertedGroup<'topology>, HybridError<InsertGroupError>>
Add more structure to the topology by creating an intermediate Group
Sibling normal objects below a common parent object can be grouped to express that there is a resource shared between the underlying CPU cores, which cannot be modeled using a more specific standard hwloc object type. For example, this is how the intra-chip NUMA clusters of modern high-core-count AMD and Intel CPUs are usually modeled. See the “What are these Group objects in my topology” entry of the hwloc FAQ for more information.
Alas, creating hwloc groups is a lot less straightforward than the above summary may suggest, and you are strongly advised to carefully read and understand all of the following before using this function.
§Group creation guide
§Basic workflow
This function will first call the find_parent
callback in order to
identify the parent object under which a new group should be inserted.
The callback(s) specified by child_filter
will then be called on
each normal and/or memory child of this parent, allowing you to tell
which objects should become members of the newly created group. See
GroupChildFilter
for more information.
This API design, which may be unexpectedly complex, helps you honor hwloc’s many group creation rules:
- Only normal and memory objects can be members of a group. I/O and
Misc
objects can only be grouped coarsely and indirectly by grouping the normal objects under which they reside. - The normal and memory members of an hwloc group must be consistent
with each other, as explained in the
GroupChildFilter
documentation. - It is, generally speaking, not possible to group objects which do not lie below the same parent. For example, you cannot create a group that contains the first hyperthreads of each core of an x86 CPU.
One extra constraint that you are responsible for honoring is that
hwloc does not support empty groups. Therefore your child_filter
callback(s) must select at least one normal or memory child.
Finally, the dont_merge
parameter allows you to adjust hwloc’s
strategy for merging proposed groups with equivalent topology objects,
as explained in the following section.
§Equivalence and merging
hwloc considers a group to be equivalent to one or more existing topology objects in the following circumstances:
- A group with a single child object is considered to be equivalent to this child object
- A group which covers all children of the parent object that was
designated by
find_parent
is considered to be equivalent to this parent object- This typically happens as a result of your children selection
callbacks returning
true
for all children of the parent object. - If you were using
GroupChildFilter::Mixed
withstrict
set tofalse
, it may also happen that although one of your callbacks did not pick all children, the remaining children had to be added to follow hwloc’s group consistency rules.
- This typically happens as a result of your children selection
callbacks returning
In addition to these equivalence relations, topology objects which form a single-child chain with identical cpusets and nodesets (a simple example being L2 -> L1d -> L1i -> Core chains in x86 topologies), are also considered to be equivalent to each other. Therefore, if a group is considered to be equivalent to one of these objects, then it is considered equivalent to all of them.
When a proposed group is equivalent to an existing topology object, the
default hwloc behavior is not to create a group, but instead to return
InsertedGroup::Existing
with one of the objects that is considered
equivalent to the proposed group as a parameter. The idea is that you do
not really need a group to model the desired set of CPU cores and NUMA
nodes, since at least one existing topology object already does so.
If you want to force the creation of a group in a situation where hwloc
would not create one, you can set dont_merge
to true
to force the
creation of a group even when hwloc considers the proposed group to be
equivalent to one existing topology object. This comes with two caveats:
- The group may be created above or below any of the objects that it is considered equivalent to, not necessarily below the parent object that you initially had in mind.
- Even with this option, hwloc will refuse to create a group that is equivalent to the topology root.
§Documenting groups
By nature, the Group
object type is not very descriptive of what the
group represents in hardware, so you may want to add extra annotations
describing what the group is about.
To this end, after a successful group object insertion, you may use
TopologyObject::set_subtype_unchecked()
to have lstopo
display something other than “Group” as the type name.
If needed, you can also complement this basic group type information
with any number of extra name/value info pairs you need using
TopologyObject::add_info()
.
§Identifier invalidation
When a group is created, it becomes a child of the group members’ former
parent. To allow for this, the normal children of this parent need to be
reordered first, so that the group members lie at consecutive indices. A
new depth level of type Group
may also need to be created to host
the group, which will push existing depths downwards. As a consequence
of all these topology changes…
- The logical indices of all objects at the depth where the group members used to lie may change as a result of calling this function. If you want to identify a child object across calls to this function, you should therefore use another identifier than the logical index or sibling rank. Global persistent indices are explicitly designed for this use case.
- The mapping of depths to object types may change as a result of calling this function, for all depths below the designated group parent. Therefore, you must be very cautious about reusing previously computed depth values across calls to this function.
§Errors
FilteredOut
if one attempts to create a group in a topology where they are filtered out usingTypeFilter::KeepNone
.BadParentType
if the designated group parent is not a normal object.ForeignParent
if the designated group parent does not belong to the topology that is being edited.Empty
if theGroupChildFilter
did not select any child.Inconsistent
ifGroupChildFilter::Mixed
was used in strict mode, but the selected normal and memory object sets were not consistent.
sourcepub fn insert_misc_object(
&mut self,
name: &str,
find_parent: impl FnOnce(&Topology) -> &TopologyObject,
) -> Result<&'topology mut TopologyObject, HybridError<InsertMiscError>>
pub fn insert_misc_object( &mut self, name: &str, find_parent: impl FnOnce(&Topology) -> &TopologyObject, ) -> Result<&'topology mut TopologyObject, HybridError<InsertMiscError>>
Add a Misc
object as a leaf of the topology
A new Misc
object will be created and inserted into the topology as
a child of the node selected by find_parent
. It is appended to the
list of existing Misc children, without ever adding any intermediate
hierarchy level. This is useful for annotating the topology without
actually changing the hierarchy.
name
is supposed to be unique across all Misc
objects in the
topology. It must not contain any NUL chars. If it contains any other
non-printable characters, then they will be dropped when exporting to
XML.
The new leaf object will not have any cpuset.
§Errors
FilteredOut
if one attempts to create a Misc object in a topology where they are filtered out usingTypeFilter::KeepNone
.ForeignParent
if the parent&TopologyObject
returned byfind_parent
does not belong to thisTopology
.NameContainsNul
ifname
contains NUL chars.NameAlreadyExists
if a Misc object calledname
already exists.