pacman.operations.router_compressors.ordered_covering_router_compressor package¶
Module contents¶
Ordered Covering¶
An novel algorithm for the minimisation of SpiNNaker’s multicast routing tables devised by Andrew Mundy.
Background¶
SpiNNaker routing tables consist of entries made up of a 32-bit key, a 32-bit mask and a 24-bit route value. The key and mask of every entry act as a sieve for the keys found on incoming multicast packets. Each bit of the key-mask pair can be considered as matching 0, 1 or 2 values in the same bit of a multicast packet key:
Key
Mask
Matches Key Values
Written
0
0
0
or1
X
0
1
0
0
1
1
1
1
1
0
Nothing
!
If a packet matches the key-mask of an entry then the packet is transmitted to the cores and links indicated by the route field.
For example, if the table were:
Key
Mask
Route
0000
1111
North, North East
0111
0111
South
Which, from now on, will be written as:
0000 -> N NE
X111 -> S
Then any packets with the key 0000
would be sent out of the north and
north-east links. Any packets with the keys 0111
or 1111
would be sent
out of the south link only.
Entries in table are ordered, with entries at the top of the table having higher priority than those lower down the table. Only the highest priority entry which matches a packet is used. If, for example, the table were:
0000 -> N NE
1111 -> 1 2
X111 -> S
Then packets with the keys 0000
and 0111
would be treated as before.
However, packets with the key 1111
would be sent to cores 1 and 2 as only
the higher priority entry has effect.
Merging routing table entries¶
Routing tables can be minimised by merging together entries with equivalent
routes. This is done by creating a new key-mask pair with an X
wherever the
key-mask pairs of any of the original entries differed.
For example, merging of the entries:
0000 -> N
0001 -> N
Would lead to the new entry:
000X -> N
Which would match any of the keys matched by the original entries but no more.
In contrast the merge of 0001
and 0010
would generate the new entry
00XX
which would match keys matched by either of the original entries but
also 0000
and 0011
.
Clearly, if we are to attempt to minimise tables such as:
0001 -> N
0010 -> N
0000 -> S, SE
0011 -> SE
We need a set of rules for:
Where merged entries are to be inserted into the table
Which merges are allowed
“Ordered Covering”¶
The algorithm implemented here, “Ordered Covering”, provides the following rule:
The only merges allowed are those which:
would not cause one of the entries in the merge to be “hidden” below an entry of lesser generality than the merged entry but which matched any of the same keys. For example, merging
0010
and0001
would not be allowed if the new entry would be placed below the existing entry000X
as this would “hide”0001
.would not cause an entry “contained” within an entry of higher generality to be hidden by the insertion of a new entry. For example, if the entry
XXXX
had been formed by merging the entries0011
and1100
then merging of the entries1101
and1110
would not be allowed as it would cause the entry11XX
to be inserted aboveXXXX
in the table and would hide1100
.
Following these rules ensures that the minimised table will be functionally equivalent to the original table provided that the original table was invariant under reordering OR was provided in increasing order of generality.
As a heuristic:
Routing tables are to be kept sorted in increasing order of “generality”, that is the number of
X``s in the entry. An entry with the key-mask pair ``00XX
must be placed below any entries with fewerX``s in their key-mask pairs (e.g., below ``0000
and000X
).
New entries must also be inserted below any entries of the same generality. If
XX00
were already present in the table the new entry0XX0
must be inserted below it.
based on https://github.com/project-rig/rig/blob/master/rig/routing_table/ordered_covering.py
Implementation API¶
- pacman.operations.router_compressors.ordered_covering_router_compressor.get_generality(key: int, mask: int) int ¶
Count the number of Xs in the key-mask pair.
For example, there are 32 Xs in
0x00000000/0x00000000
:>>> get_generality(0x0, 0x0) 32
And no Xs in
0xffffffff/0xffffffff
:>>> get_generality(0xffffffff, 0xffffffff) 0
- pacman.operations.router_compressors.ordered_covering_router_compressor.intersect(key_a: int, mask_a: int, key_b: int, mask_b: int) bool ¶
Return if key-mask pairs intersect (i.e., would both match some of the same keys).
For example, the key-mask pairs
00XX
and001X
both match the keys0010
and0011
(i.e., they do intersect):>>> intersect(0b0000, 0b1100, 0b0010, 0b1110) True
But the key-mask pairs
00XX
and11XX
do not match any of the same keys (i.e., they do not intersect):>>> intersect(0b0000, 0b1100, 0b1100, 0b1100) False
- pacman.operations.router_compressors.ordered_covering_router_compressor.ordered_covering(routing_table: Iterable[MulticastRoutingEntry], target_length: int | None, aliases: Dict[Tuple[int, int], FrozenSet[Tuple[int, int]]], *, no_raise: bool = False, time_to_run_for: float | None = None) Tuple[List[MulticastRoutingEntry], Dict[Tuple[int, int], FrozenSet[Tuple[int, int]]]] ¶
Reduce the size of a routing table by merging together entries where possible.
Warning
The input routing table must also include entries which could be removed and replaced by default routing.
Warning
It is assumed that the input routing table is not in any particular order and may be reordered into ascending order of generality (number of don’t cares/Xs in the key-mask) without affecting routing correctness. It is also assumed that if this table is unordered it is at least orthogonal (i.e., there are no two entries which would match the same key) and reorderable.
- Parameters:
routing_table (iterable(MulticastRoutingEntry)) – Routing entries to be merged.
target_length (int or None) – Target length of the routing table; the minimisation procedure will halt once either this target is reached or no further minimisation is possible. If None then the table will be made as small as possible.
aliases (dict(tuple(int, int), set(tuple(int, int))) – Dictionary of which keys and masks in the routing table are combinations of other (now removed) keys and masks; this allows us to consider only the keys and masks the user actually cares about when determining if inserting a new entry will break the correctness of the table. This should be supplied when using this method to update an already minimised table, and should be an empty dictionary when compressing an uncompressed routing table.
no_raise (bool) – If False (the default) then an error will be raised if the table cannot be minimised to be smaller than target_length and target_length is not None. If True then a table will be returned regardless of the size of the final table.
time_to_run_for (float) – If supplied, a maximum number of seconds to run for before giving an error. May only be obeyed approximately.
- Returns:
new routing table, A new _aliases dictionary.
- Return type:
tuple(list(MulticastRoutingEntry), dict(tuple(int,int), set(tuple(int,int))))
- Raises:
MinimisationFailedError – If the smallest table that can be produced is larger than
target_length
.
- pacman.operations.router_compressors.ordered_covering_router_compressor.ordered_covering_compressor() MulticastRoutingTables ¶
Compressor from rig that has been tied into the main tool chain stack.
- Return type:
- pacman.operations.router_compressors.ordered_covering_router_compressor.remove_default_routes(table: List[MulticastRoutingEntry], target_length: int | None, check_for_aliases: bool = True) List[MulticastRoutingEntry] ¶
Remove from the routing table any entries which could be replaced by default routing.
- Parameters:
table (list(router_table.multicast_routing_entries)) – Routing entries to be merged.
target_length (int or None) – Target length of the routing table; the minimisation procedure will halt once either this target is reached or no further minimisation is possible. If
None
then the table will be made as small as possible.check_for_aliases (bool) –
If
True
(the default), default-route candidates are checked for aliased entries before suggesting a route may be default routed. This check is required to ensure correctness in the general case but has a runtime complexity of O(N2) in the worst case for N-entry tables.If
False
, the alias-check is skipped resulting in O(N) runtime. This option should only be used if the supplied table is guaranteed not to contain any aliased entries.
- Return type:
list(MulticastRoutingEntry)
- Raises:
MinimisationFailedError – If the smallest table that can be produced is larger than
target_length
.