def test_multicast_routing_table_by_partition_entry(self):
     e1 = MulticastRoutingTableByPartitionEntry(range(18), range(6))
     with self.assertRaises(PacmanInvalidParameterException):
         MulticastRoutingTableByPartitionEntry(range(18), range(6), 4, 3)
     e2 = MulticastRoutingTableByPartitionEntry(
         range(4), range(2), incoming_processor=4)
     e3 = MulticastRoutingTableByPartitionEntry(
         range(12, 16), range(3, 5), incoming_link=3)
     with self.assertRaises(PacmanInvalidParameterException):
         MulticastRoutingTableByPartitionEntry(range(18), range(6),
                                               incoming_link=[])
     e4 = MulticastRoutingTableByPartitionEntry(16, 2)
     e5 = MulticastRoutingTableByPartitionEntry(None, None)
     assert str(e2) == "None:4:False:{0, 1, 2, 3}:{0, 1}"
     assert str(e3) == "3:None:False:{12, 13, 14, 15}:{3, 4}"
     with self.assertRaises(PacmanInvalidParameterException):
         e2.merge_entry(e3)
     e6 = e2.merge_entry(MulticastRoutingTableByPartitionEntry(
         range(12, 16), range(3, 5)))
     assert str(e2) == "None:4:False:{0, 1, 2, 3}:{0, 1}"
     assert str(e6) == (
         "None:4:False:{0, 1, 2, 3, 12, 13, 14, 15}:{0, 1, 3, 4}")
     e6 = e3.merge_entry(MulticastRoutingTableByPartitionEntry(
         range(4), range(2)))
     assert str(e3) == "3:None:False:{12, 13, 14, 15}:{3, 4}"
     assert str(e6) == (
         "3:None:False:{0, 1, 2, 3, 12, 13, 14, 15}:{0, 1, 3, 4}")
     assert str(e4.merge_entry(e5)) == "None:None:False:{16}:{2}"
     assert str(e1) == str(e5.merge_entry(e1))
     # NB: Have true object identity; we have setters!
     assert e5 != MulticastRoutingTableByPartitionEntry(None, None)
Beispiel #2
0
def _convert_next_route(routing_tables, partition, incoming_processor,
                        incoming_link, partition_route):
    x, y = partition_route.chip

    next_hops = list()
    processor_ids = list()
    link_ids = list()
    for (route, next_hop) in partition_route.children:
        if route is not None:
            link = None
            if isinstance(route, Routes):
                if route.is_core:
                    processor_ids.append(route.core_num)
                else:
                    link = route.value
                    link_ids.append(link)
            elif isinstance(route, Links):
                link = route.value
                link_ids.append(link)
            if isinstance(next_hop, RoutingTree):
                next_incoming_link = None
                if link is not None:
                    next_incoming_link = (link + 3) % 6
                next_hops.append((next_hop, next_incoming_link))

    routing_tables.add_path_entry(
        MulticastRoutingTableByPartitionEntry(link_ids, processor_ids,
                                              incoming_processor,
                                              incoming_link), x, y, partition)

    for next_hop, next_incoming_link in next_hops:
        _convert_next_route(routing_tables, partition, None,
                            next_incoming_link, next_hop)
    def _convert_next_route(routing_tables, partition, incoming_processor,
                            incoming_link, partition_route):
        x, y = partition_route["chip"]

        next_hops = list()
        processor_ids = list()
        link_ids = list()
        for child in partition_route["children"]:
            route = child["route"]
            next_hop = child["next_hop"]
            if route is not None:
                is_core, route_id = _route_translation[route.upper()]
                if is_core:
                    processor_ids.append(route_id)
                else:
                    link_ids.append(route_id)
                if isinstance(next_hop, dict):
                    next_incoming_link = None
                    if not is_core:
                        next_incoming_link = (route_id + 3) % 6
                    next_hops.append((next_hop, next_incoming_link))

        routing_tables.add_path_entry(
            MulticastRoutingTableByPartitionEntry(link_ids, processor_ids,
                                                  incoming_processor,
                                                  incoming_link), x, y,
            partition)

        for next_hop, next_incoming_link in next_hops:
            ConvertToMemoryMultiCastRoutes._convert_next_route(
                routing_tables, partition, None, next_incoming_link, next_hop)
Beispiel #4
0
 def test_multicast_routing_table_by_partition(self):
     mrt = MulticastRoutingTableByPartition()
     partition = MulticastEdgePartition(None, "foo")
     entry = MulticastRoutingTableByPartitionEntry(range(4), range(2))
     mrt.add_path_entry(entry, 0, 0, partition)
     entry = MulticastRoutingTableByPartitionEntry(range(4, 8), range(2, 4))
     mrt.add_path_entry(entry, 0, 0, partition)
     entry = MulticastRoutingTableByPartitionEntry(range(8, 12),
                                                   range(4, 6))
     mrt.add_path_entry(entry, 0, 0, partition)
     assert list(mrt.get_routers()) == [(0, 0)]
     assert len(mrt.get_entries_for_router(0, 0)) == 1
     assert next(iter(mrt.get_entries_for_router(0, 0))) == partition
     mre = mrt.get_entries_for_router(0, 0)[partition]
     assert str(mre) == (
         "None:None:False:{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}"
         ":{0, 1, 2, 3, 4, 5}")
     assert mre == mrt.get_entry_on_coords_for_edge(partition, 0, 0)
Beispiel #5
0
    def _create_routing_entry(self, neighbour_xy, tables, neighbour_index,
                              nodes_info, x, y, previous_entry, edge, graph):
        """ Create a new routing entry

        :param tuple(int,int) neighbour_xy:
        :param dict(tuple(int,int),_DijkstraInfo) tables:
        :param int neighbour_index:
        :param dict(tuple(int,int),_NodeInfo) nodes_info:
        :param int x:
        :param int y:
        :param MulticastRoutingTableByPartitionEntry previous_entry:
        :param MachineEdge edge:
        :param MachineGraph graph:
        :return: x, y, previous_entry, made_an_entry
        :rtype: tuple(int, int, MulticastRoutingTableByPartitionEntry, bool)
        :raise PacmanRoutingException:
            when the bandwidth of a router is beyond expected parameters
        """

        # Set the direction of the routing other_entry as that which is from
        # the preceding node to the current tracking node.
        # neighbour_xy is the 'old' coordinates since it is from the preceding
        # node. x and y are the 'new' coordinates since they are where the
        # router should send the packet to.
        dec_direction = self._get_reverse_direction(neighbour_index)
        made_an_entry = False

        neighbour_weight = nodes_info[neighbour_xy].weights[dec_direction]
        chip_sought_cost = tables[x, y].cost - neighbour_weight
        neighbours_lowest_cost = tables[neighbour_xy].cost

        if (neighbours_lowest_cost is not None and self._close_enough(
                neighbours_lowest_cost, chip_sought_cost)):
            # build the multicast entry
            partns = graph.get_multicast_edge_partitions_starting_at_vertex(
                edge.pre_vertex)
            entry = None
            for partition in partns:
                if edge in partition:
                    entry = MulticastRoutingTableByPartitionEntry(
                        dec_direction, None)
                    previous_entry.incoming_link = neighbour_index
                    # add entry for next hop going backwards into path
                    self._routing_paths.add_path_entry(entry, neighbour_xy[0],
                                                       neighbour_xy[1],
                                                       partition)
            previous_entry = entry
            made_an_entry = True

            # Finally move the tracking node
            x, y = neighbour_xy

        return x, y, previous_entry, made_an_entry
def _convert_a_route(routing_tables, partition, incoming_processor,
                     incoming_link, partition_route):
    """
    Converts the algorithm specific partition_route back to standard spinnaker
    and ands it to the routing_tables.

    :param MulticastRoutingTableByPartition routing_tables:
        spinnaker format routing tables
    :param AbstractSingleSourcePartition partition: \
        Partition this route applies to
    :param int or None incoming_processor: processor this link came from
    :param int or None incoming_link: link this link came from
    :param RoutingTree partition_route: algorithm specific format of the route
    """
    x, y = partition_route.chip

    next_hops = list()
    processor_ids = list()
    link_ids = list()
    for (route, next_hop) in partition_route.children:
        if route is not None:
            next_incoming_link = None
            if route >= 6:
                # The route was offset as first 6 are the links
                processor_ids.append(route - 6)
            else:
                link_ids.append(route)
                next_incoming_link = (route + 3) % 6
            if isinstance(next_hop, RoutingTree):
                next_hops.append((next_hop, next_incoming_link))

    entry = MulticastRoutingTableByPartitionEntry(link_ids, processor_ids,
                                                  incoming_processor,
                                                  incoming_link)
    routing_tables.add_path_entry(entry, x, y, partition)

    for next_hop, next_incoming_link in next_hops:
        _convert_a_route(routing_tables, partition, None, next_incoming_link,
                         next_hop)
Beispiel #7
0
 def test_multicast_routing_table_by_partition_entry(self):
     e1 = MulticastRoutingTableByPartitionEntry(range(18), range(6))
     with self.assertRaises(PacmanInvalidParameterException):
         MulticastRoutingTableByPartitionEntry(range(18), range(6), 4, 3)
     e2 = MulticastRoutingTableByPartitionEntry(range(4),
                                                range(2),
                                                incoming_processor=4)
     e3 = MulticastRoutingTableByPartitionEntry(range(12, 16),
                                                range(3, 5),
                                                incoming_link=3)
     with self.assertRaises(PacmanInvalidParameterException):
         MulticastRoutingTableByPartitionEntry(range(18),
                                               range(6),
                                               incoming_link=[])
     e4 = MulticastRoutingTableByPartitionEntry(16, 2)
     e5 = MulticastRoutingTableByPartitionEntry(None, None)
     assert str(e2) == "None:4:False:{0, 1, 2, 3}:{0, 1}"
     assert str(e3) == "3:None:False:{12, 13, 14, 15}:{3, 4}"
     with self.assertRaises(PacmanInvalidParameterException):
         e2.merge_entry(e3)
     e6 = e2.merge_entry(
         MulticastRoutingTableByPartitionEntry(range(12, 16), range(3, 5)))
     assert str(e2) == "None:4:False:{0, 1, 2, 3}:{0, 1}"
     assert str(e6) == (
         "None:4:False:{0, 1, 2, 3, 12, 13, 14, 15}:{0, 1, 3, 4}")
     e6 = e3.merge_entry(
         MulticastRoutingTableByPartitionEntry(range(4), range(2)))
     assert str(e3) == "3:None:False:{12, 13, 14, 15}:{3, 4}"
     assert str(e6) == (
         "3:None:False:{0, 1, 2, 3, 12, 13, 14, 15}:{0, 1, 3, 4}")
     assert str(e4.merge_entry(e5)) == "None:None:False:{16}:{2}"
     assert str(e1) == str(e5.merge_entry(e1))
     # NB: Have true object identity; we have setters!
     assert e5 != MulticastRoutingTableByPartitionEntry(None, None)
Beispiel #8
0
    def _retrace_back_to_source(self, dest, tables, edge, nodes_info,
                                source_processor, graph):
        """
        :param Placement dest: Destination placement
        :param dict(tuple(int,int),_DijkstraInfo) tables:
        :param MachineEdge edge:
        :param dict(tuple(int,int),_NodeInfo) nodes_info:
        :param int source_processor:
        :param MachineGraph graph:
        :return: the next coordinates to look into
        :rtype: tuple(int, int)
        :raise PacmanRoutingException:
            when the algorithm doesn't find a next point to search from. AKA,
            the neighbours of a chip do not have a cheaper cost than the node
            itself, but the node is not the destination or when the algorithm
            goes to a node that's not considered in the weighted search.
        """
        # Set the tracking node to the destination to begin with
        x, y = dest.x, dest.y
        routing_entry_route_processors = []

        # if the processor is None, don't add to router path entry
        if dest.p is not None:
            routing_entry_route_processors.append(dest.p)
        routing_entry_route_links = None

        # build the multicast entry
        partitions = graph.get_multicast_edge_partitions_starting_at_vertex(
            edge.pre_vertex)

        prev_entry = None
        for partition in partitions:
            if edge in partition:
                entry = MulticastRoutingTableByPartitionEntry(
                    out_going_links=routing_entry_route_links,
                    outgoing_processors=routing_entry_route_processors)
                self._routing_paths.add_path_entry(entry, dest.x, dest.y,
                                                   partition)
                prev_entry = entry

        while tables[x, y].cost != 0:
            for idx, neighbour in enumerate(nodes_info[x, y].neighbours):
                if neighbour is not None:
                    n_xy = (neighbour.destination_x, neighbour.destination_y)

                    # Only check if it can be a preceding node if it actually
                    # exists
                    if n_xy not in tables:
                        raise PacmanRoutingException(
                            "Tried to trace back to node not in "
                            "graph: remove non-existent neighbours")

                    if tables[n_xy].cost is not None:
                        x, y, prev_entry, added = self._create_routing_entry(
                            n_xy, tables, idx, nodes_info, x, y, prev_entry,
                            edge, graph)
                        if added:
                            break
            else:
                raise PacmanRoutingException(
                    "Iterated through all neighbours of tracking node but"
                    " did not find a preceding node! Consider increasing "
                    "acceptable discrepancy between sought traceback cost"
                    " and actual cost at node. Terminating...")
        prev_entry.incoming_processor = source_processor
        return x, y