Example #1
0
    def __call__(self, partitioned_graph, machine):

        # check that the algorithm can handle the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=partitioned_graph.subvertices,
            supported_constraints=[
                PlacerRadialPlacementFromChipConstraint,
                TagAllocatorRequireIptagConstraint,
                TagAllocatorRequireReverseIptagConstraint,
                PlacerChipAndCoreConstraint],
            abstract_constraint_type=AbstractPlacerConstraint)

        placements = Placements()
        ordered_subverts = utility_calls.sort_objects_by_constraint_authority(
            partitioned_graph.subvertices)

        # Iterate over subvertices and generate placements
        progress_bar = ProgressBar(len(ordered_subverts),
                                   "Placing graph vertices")
        resource_tracker = ResourceTracker(
            machine, self._generate_radial_chips(machine))
        for vertex in ordered_subverts:
            self._place_vertex(vertex, resource_tracker, machine, placements)
            progress_bar.update()
        progress_bar.end()
        return {'placements': placements}
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param MachineGraph machine_graph:
            The graph to allocate the routing info for
        :param Placements placements: The placements of the vertices
        :param AbstractMachinePartitionNKeysMap n_keys_map:
            A map between the edges and the number of keys required by the
            edges
        :return: The routing information
        :rtype: tuple(RoutingInfo, AbstractMulticastRoutingTable)
        :raise PacmanRouteInfoAllocationException:
            If something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitions
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.partitions,
            supported_constraints=[],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()

        for partition in progress.over(machine_graph.outgoing_edge_partitions):
            for edge in partition.edges:
                routing_infos.add_partition_info(
                    self._allocate_partition_route(edge, placements,
                                                   machine_graph, n_keys_map))

        return routing_infos, routing_tables
    def __call__(self, partitioned_graph, machine):
        """

        :param partitioned_graph: The partitioned_graph to measure
        :type partitioned_graph:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :return: The size of the graph in number of chips
        :rtype: int
        """

        # check that the algorithm can handle the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=partitioned_graph.subvertices,
            supported_constraints=[PlacerChipAndCoreConstraint],
            abstract_constraint_type=AbstractPlacerConstraint)

        ordered_subverts = utility_calls.sort_objects_by_constraint_authority(
            partitioned_graph.subvertices)

        # Iterate over subvertices and allocate
        progress_bar = ProgressBar(len(ordered_subverts),
                                   "Measuring the partitioned graph")
        resource_tracker = ResourceTracker(machine)
        for subvertex in ordered_subverts:
            resource_tracker.allocate_constrained_resources(
                subvertex.resources_required, subvertex.constraints)
            progress_bar.update()
        progress_bar.end()
        return {'n_chips': len(resource_tracker.keys)}
Example #4
0
    def __call__(self, partitioned_graph, machine):

        # check that the algorithm can handle the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=partitioned_graph.subvertices,
            supported_constraints=[
                PlacerRadialPlacementFromChipConstraint,
                TagAllocatorRequireIptagConstraint,
                TagAllocatorRequireReverseIptagConstraint,
                PlacerChipAndCoreConstraint],
            abstract_constraint_type=AbstractPlacerConstraint)

        placements = Placements()
        ordered_subverts = utility_calls.sort_objects_by_constraint_authority(
            partitioned_graph.subvertices)

        # Iterate over subvertices and generate placements
        progress_bar = ProgressBar(len(ordered_subverts),
                                   "Placing graph vertices")
        resource_tracker = ResourceTracker(
            machine, self._generate_radial_chips(machine))
        for vertex in ordered_subverts:
            self._place_vertex(vertex, resource_tracker, machine, placements)
            progress_bar.update()
        progress_bar.end()
        return {'placements': placements}
 def check_supported_constraints(self):
     utility_calls.check_algorithm_can_support_constraints(
         constrained_vertices=[self._governed_app_vertex],
         supported_constraints=[
             MaxVertexAtomsConstraint, FixedVertexAtomsConstraint
         ],
         abstract_constraint_type=AbstractPartitionerConstraint)
Example #6
0
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param MachineGraph machine_graph:
            The machine graph to allocate the routing info for
        :param Placements placements: The placements of the vertices
        :param AbstractMachinePartitionNKeysMap n_keys_map:
            A map between the edges and the number of keys required by the
            edges
        :return: The routing information
        :rtype: PartitionRoutingInfo
        :raise PacmanRouteInfoAllocationException:
            If something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitions
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[ContiguousKeyRangeContraint],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_vertices,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        for vertex in progress.over(machine_graph.vertices):
            for partition in machine_graph.\
                    get_multicast_edge_partitions_starting_at_vertex(vertex):
                routing_infos.add_partition_info(
                    self._allocate_key_for_partition(partition, vertex,
                                                     placements, n_keys_map))
        return routing_infos
    def __call__(self, subgraph, n_keys_map, routing_paths):

        # check that this algorithm supports the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.subedges,
            supported_constraints=[
                KeyAllocatorFixedMaskConstraint,
                KeyAllocatorFixedKeyAndMaskConstraint,
                KeyAllocatorContiguousRangeContraint],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        routing_tables = MulticastRoutingTables()

        # Get the partitioned edges grouped by those that require the same key
        same_key_groups = \
            routing_info_allocator_utilities.get_edge_groups(subgraph)

        # Go through the groups and allocate keys
        progress_bar = ProgressBar(len(same_key_groups),
                                   "Allocating routing keys")
        routing_infos = RoutingInfo()
        for group in same_key_groups:
            # Check how many keys are needed for the edges of the group
            edge_n_keys = None
            for edge in group:
                n_keys = n_keys_map.n_keys_for_partitioned_edge(edge)
                if edge_n_keys is None:
                    edge_n_keys = n_keys
                elif edge_n_keys != n_keys:
                    raise PacmanRouteInfoAllocationException(
                        "Two edges require the same keys but request a"
                        " different number of keys")

            # Get any fixed keys and masks from the group and attempt to
            # allocate them
            keys_and_masks = routing_info_allocator_utilities.\
                get_fixed_key_and_mask(group)
            fixed_mask, fields = \
                routing_info_allocator_utilities.get_fixed_mask(group)

            if keys_and_masks is not None:

                self._allocate_fixed_keys_and_masks(keys_and_masks, fixed_mask)
            else:
                keys_and_masks = self._allocate_keys_and_masks(
                    fixed_mask, fields, edge_n_keys)

            # Allocate the routing information
            for edge in group:
                subedge_info = SubedgeRoutingInfo(keys_and_masks, edge)
                routing_infos.add_subedge_info(subedge_info)

                # update routing tables with entries
                routing_info_allocator_utilities.add_routing_key_entries(
                    routing_paths, subedge_info, edge, routing_tables)

            progress_bar.update()
        progress_bar.end()
        return {'routing_infos': routing_infos,
                'routing_tables': routing_tables}
    def __call__(self, machine_graph, n_keys_map, graph_mapper=None):
        # check that this algorithm supports the constraints
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[
                FixedMaskConstraint,
                FixedKeyAndMaskConstraint,
                ContiguousKeyRangeContraint, ShareKeyConstraint],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # verify that no edge has more than 1 of a constraint ,and that
        # constraints are compatible
        check_types_of_edge_constraint(machine_graph)

        # final keys allocations
        routing_infos = RoutingInfo()

        # Get the edges grouped by those that require the same key
        (fixed_keys, shared_keys, fixed_masks, fixed_fields, flexi_fields,
         continuous, noncontinuous) = get_edge_groups(
             machine_graph, EdgeTrafficType.MULTICAST)

        # Go through the groups and allocate keys
        progress = ProgressBar(
            machine_graph.n_outgoing_edge_partitions,
            "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in progress.over(fixed_keys, False):
            self._allocate_fixed_keys(group, routing_infos)

        for group in progress.over(fixed_masks, False):
            self._allocate_fixed_masks(group, n_keys_map, routing_infos)

        for group in progress.over(fixed_fields, False):
            self._allocate_fixed_fields(group, n_keys_map, routing_infos)

        if flexi_fields:
            raise PacmanConfigurationException(
                "MallocBasedRoutingInfoAllocator does not support FlexiField")

        for group in progress.over(shared_keys, False):
            self._allocate_share_key(group, routing_infos, n_keys_map)

        for group in continuous:
            self._allocate_other_groups(group, routing_infos, n_keys_map,
                                        continuous=True)

        for group in noncontinuous:
            self._allocate_other_groups(group, routing_infos, n_keys_map,
                                        continuous=False)

        progress.end()
        return routing_infos
    def __call__(self, machine_graph, n_keys_map, graph_mapper=None):
        # check that this algorithm supports the constraints
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[
                FixedMaskConstraint, FixedKeyAndMaskConstraint,
                ContiguousKeyRangeContraint, ShareKeyConstraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # verify that no edge has more than 1 of a constraint ,and that
        # constraints are compatible
        utilities.check_types_of_edge_constraint(machine_graph)

        # final keys allocations
        routing_infos = RoutingInfo()

        # Get the edges grouped by those that require the same key
        (fixed_keys, shared_keys, fixed_masks, fixed_fields, flexi_fields,
         continuous,
         noncontinuous) = utilities.get_edge_groups(machine_graph,
                                                    EdgeTrafficType.MULTICAST)

        # Even non-continuous keys will be continuous
        for group in noncontinuous:
            continuous.append(group)

        # Go through the groups and allocate keys
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in progress.over(fixed_keys, False):
            self._allocate_fixed_keys(group, routing_infos)

        for group in progress.over(fixed_masks, False):
            self._allocate_fixed_masks(group, n_keys_map, routing_infos)

        for group in progress.over(fixed_fields, False):
            self._allocate_fixed_fields(group, n_keys_map, routing_infos)

        if flexi_fields:
            raise PacmanConfigurationException(
                "MallocBasedRoutingInfoAllocator does not support FlexiField")

        for group in progress.over(shared_keys, False):
            self._allocate_share_key(group, routing_infos, n_keys_map)

        for group in continuous:
            self._allocate_continuous_groups(group, routing_infos, n_keys_map)

        progress.end()
        return routing_infos
    def __call__(self, machine_graph, n_keys_map):
        """
        :param MachineGraph machine_graph:
        :param AbstractMachinePartitionNKeysMap n_keys_map:
        :rtype: RoutingInfo
        :raises PacmanRouteInfoAllocationException:
        """
        self._n_keys_map = n_keys_map
        # check that this algorithm supports the constraints
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[
                FixedMaskConstraint, FixedKeyAndMaskConstraint,
                ContiguousKeyRangeContraint, ShareKeyConstraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # verify that no edge has more than 1 of a constraint ,and that
        # constraints are compatible
        check_types_of_edge_constraint(machine_graph)

        # final keys allocations
        routing_infos = RoutingInfo()

        # Get the edges grouped by those that require the same key
        (fixed_keys, shared_keys, fixed_masks, fixed_fields, continuous,
         noncontinuous) = get_mulitcast_edge_groups(machine_graph)

        # Go through the groups and allocate keys
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in progress.over(fixed_keys, False):
            self._allocate_fixed_keys(group, routing_infos)

        for group in progress.over(fixed_masks, False):
            self._allocate_fixed_masks(group, routing_infos)

        for group in progress.over(fixed_fields, False):
            self._allocate_fixed_fields(group, routing_infos)

        for group in progress.over(shared_keys, False):
            self._allocate_share_key(group, routing_infos)

        for group in continuous:
            self._allocate_other_groups(group, routing_infos, True)

        for group in noncontinuous:
            self._allocate_other_groups(group, routing_infos, False)

        progress.end()
        return routing_infos
Example #11
0
 def check_supported_constraints(self):
     """
     :raise PacmanInvalidParameterException:
         When partitioner constraints other than
         :py:class:`MaxVertexAtomsConstraint` and
         :py:class:`FixedVertexAtomsConstraint` are used.
     """
     utility_calls.check_algorithm_can_support_constraints(
         constrained_vertices=[self._governed_app_vertex],
         supported_constraints=[
             MaxVertexAtomsConstraint, FixedVertexAtomsConstraint],
         abstract_constraint_type=AbstractPartitionerConstraint)
Example #12
0
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param machine_graph: The graph to allocate the routing info for
        :type machine_graph:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :param placements: The placements of the vertices
        :type placements:\
            :py:class:`pacman.model.placements.Placements`
        :param n_keys_map: A map between the edges and the number of keys\
            required by the edges
        :type n_keys_map:\
            :py:class:`pacman.model.routing_info.AbstractMachinePartitionNKeysMap`
        :return: The routing information
        :rtype: \
            :py:class:`pacman.model.routing_info.RoutingInfo`, \
            :py:class:`pacman.model.routing_tables.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: \
            If something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitions
        supported_constraints = []
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.partitions,
            supported_constraints=supported_constraints,
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()

        for partition in progress.over(machine_graph.outgoing_edge_partitions):
            for edge in partition.edges:
                routing_infos.add_partition_info(
                    self._allocate_partition_route(edge, placements,
                                                   machine_graph, n_keys_map))

        return routing_infos, routing_tables
Example #13
0
    def __call__(self, partitioned_graph, machine):

        sorted_vertices = self._sort_vertices_for_one_to_one_connection(
            partitioned_graph)

        # check that the algorithm can handle the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=partitioned_graph.subvertices,
            supported_constraints=[
                PlacerRadialPlacementFromChipConstraint,
                TagAllocatorRequireIptagConstraint,
                TagAllocatorRequireReverseIptagConstraint,
                PlacerChipAndCoreConstraint
            ],
            abstract_constraint_type=AbstractPlacerConstraint)

        placements = Placements()

        self._do_allocation(sorted_vertices, placements, machine)

        return {'placements': placements}
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param machine_graph: The graph to allocate the routing info for
        :type machine_graph:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :param placements: The placements of the vertices
        :type placements:\
            :py:class:`pacman.model.placements.Placements`
        :param n_keys_map: A map between the edges and the number of keys\
            required by the edges
        :type n_keys_map:\
            :py:class:`pacman.model.routing_info.AbstractMachinePartitionNKeysMap`
        :return: The routing information
        :rtype: \
            :py:class:`pacman.model.routing_info.RoutingInfo`, \
            :py:class:`pacman.model.routing_tables.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: \
            If something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitions
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.partitions,
            supported_constraints=[],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()

        for partition in progress.over(machine_graph.outgoing_edge_partitions):
            for edge in partition.edges:
                routing_infos.add_partition_info(
                    self._allocate_partition_route(
                        edge, placements, machine_graph, n_keys_map))

        return routing_infos, routing_tables
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param machine_graph:\
            The machine graph to allocate the routing info for
        :type machine_graph:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :param placements: The placements of the vertices
        :type placements:\
            :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map:\
            A map between the edges and the number of keys required by the\
            edges
        :type n_keys_map:\
            :py:class:`pacman.model.routing_info.AbstractMachinePartitionNKeysMap`
        :return: The routing information
        :rtype:\
            :py:class:`pacman.model.routing_info.PartitionRoutingInfo`
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: \
            If something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitions
        supported_constraints = [ContiguousKeyRangeContraint]
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=supported_constraints,
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each edge and create keys from its placement
        progress = ProgressBar(machine_graph.n_vertices,
                               "Allocating routing keys")
        routing_infos = RoutingInfo()
        for vertex in progress.over(machine_graph.vertices):
            for partition in machine_graph.\
                    get_outgoing_edge_partitions_starting_at_vertex(vertex):
                routing_infos.add_partition_info(
                    self._allocate_key_for_partition(partition, vertex,
                                                     placements, n_keys_map))
        return routing_infos
    def __call__(self, machine_graph, placements, n_keys_map):
        """
        :param machine_graph:\
            The machine graph to allocate the routing info for
        :type machine_graph:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :param placements: The placements of the vertices
        :type placements:\
            :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map:\
            A map between the edges and the number of keys required by the\
            edges
        :type n_keys_map:\
            :py:class:`pacman.model.routing_info.AbstractMachinePartitionNKeysMap`
        :return: The routing information
        :rtype:\
            :py:class:`pacman.model.routing_info.PartitionRoutingInfo`
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: \
            If something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitions
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[ContiguousKeyRangeContraint],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each edge and create keys from its placement
        progress = ProgressBar(
            machine_graph.n_vertices, "Allocating routing keys")
        routing_infos = RoutingInfo()
        for vertex in progress.over(machine_graph.vertices):
            for partition in machine_graph.\
                    get_outgoing_edge_partitions_starting_at_vertex(vertex):
                routing_infos.add_partition_info(
                    self._allocate_key_for_partition(
                        partition, vertex, placements, n_keys_map))
        return routing_infos
    def __call__(self, graph, machine, plan_n_timesteps):
        """
        :param graph: The application_graph to partition
        :type graph:\
            :py:class:`pacman.model.graphs.application.ApplicationGraph`
        :param machine:\
            The machine with respect to which to partition the application\
            graph
        :type machine: :py:class:`spinn_machine.Machine`
        :param plan_n_timesteps: number of timesteps to plan for
        :type  plan_n_timesteps: int
        :return: A machine graph
        :rtype:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :raise pacman.exceptions.PacmanPartitionException:\
            If something goes wrong with the partitioning
        """
        ResourceTracker.check_constraints(graph.vertices)
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=graph.vertices,
            supported_constraints=[
                MaxVertexAtomsConstraint, FixedVertexAtomsConstraint],
            abstract_constraint_type=AbstractPartitionerConstraint)

        # start progress bar
        progress = ProgressBar(graph.n_vertices, "Partitioning graph vertices")
        machine_graph = MachineGraph("Machine graph for " + graph.label)
        graph_mapper = GraphMapper()
        resource_tracker = ResourceTracker(machine, plan_n_timesteps)

        # Partition one vertex at a time
        for vertex in progress.over(graph.vertices):
            self._partition_one_application_vertex(
                vertex, resource_tracker, machine_graph, graph_mapper,
                plan_n_timesteps)

        generate_machine_edges(machine_graph, graph_mapper, graph)

        return machine_graph, graph_mapper, resource_tracker.chips_used
    def __call__(self, machine_graph, n_keys_map, flexible):
        """
        :param MachineGraph machine_graph:
            The machine graph to allocate the routing info for
        :param AbstractMachinePartitionNKeysMap n_keys_map:
            A map between the edges and the number of keys required by the
            edges
        :param bool flexible: Determines if flexible can be use.
            If False, global settings will be attempted
        :return: The routing information
        :rtype: RoutingInfo
        :raise PacmanRouteInfoAllocationException:
            If something goes wrong with the allocation
        """
        # check that this algorithm supports the constraints put onto the
        # partitions
        self.__machine_graph = machine_graph
        self.__n_keys_map = n_keys_map
        self.__n_bits_atoms_and_mac = 0
        self.__n_bits_machine = 0
        self.__n_bits_atoms = 0
        self.__atom_bits_per_app_part = dict()
        self.__flexible = flexible
        self.__fixed_keys = list()
        self.__fixed_partitions = dict()
        self.__fixed_used = set()

        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[
                ContiguousKeyRangeContraint, FixedKeyAndMaskConstraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        self.__find_fixed()
        self.__calculate_zones()
        self.__check_zones()
        return self.__allocate()
Example #19
0
    def __call__(self, partitioned_graph, machine):
        """ Place a partitioned_graph so that each subvertex is placed on a\
                    core

        :param partitioned_graph: The partitioned_graph to place
        :type partitioned_graph:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :return: A set of placements
        :rtype: :py:class:`pacman.model.placements.placements.Placements`
        :raise pacman.exceptions.PacmanPlaceException: If something\
                   goes wrong with the placement
        """

        # check that the algorithm can handle the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=partitioned_graph.subvertices,
            supported_constraints=[PlacerChipAndCoreConstraint],
            abstract_constraint_type=AbstractPlacerConstraint)

        placements = Placements()
        ordered_subverts = utility_calls.sort_objects_by_constraint_authority(
            partitioned_graph.subvertices)

        # Iterate over subvertices and generate placements
        progress_bar = ProgressBar(len(ordered_subverts),
                                   "Placing graph vertices")
        resource_tracker = ResourceTracker(machine)
        for subvertex in ordered_subverts:

            # Create and store a new placement anywhere on the board
            (x, y, p, _, _) = resource_tracker.allocate_constrained_resources(
                subvertex.resources_required, subvertex.constraints)
            placement = Placement(subvertex, x, y, p)
            placements.add_placement(placement)
            progress_bar.update()
        progress_bar.end()
        return {'placements': placements}
Example #20
0
    def __call__(self, partitioned_graph, machine):
        """ Place a partitioned_graph so that each subvertex is placed on a\
                    core

        :param partitioned_graph: The partitioned_graph to place
        :type partitioned_graph:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :return: A set of placements
        :rtype: :py:class:`pacman.model.placements.placements.Placements`
        :raise pacman.exceptions.PacmanPlaceException: If something\
                   goes wrong with the placement
        """

        # check that the algorithm can handle the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=partitioned_graph.subvertices,
            supported_constraints=[PlacerChipAndCoreConstraint],
            abstract_constraint_type=AbstractPlacerConstraint)

        placements = Placements()
        ordered_subverts = utility_calls.sort_objects_by_constraint_authority(
            partitioned_graph.subvertices)

        # Iterate over subvertices and generate placements
        progress_bar = ProgressBar(len(ordered_subverts),
                                   "Placing graph vertices")
        resource_tracker = ResourceTracker(machine)
        for subvertex in ordered_subverts:

            # Create and store a new placement anywhere on the board
            (x, y, p, _, _) = resource_tracker.allocate_constrained_resources(
                subvertex.resources_required, subvertex.constraints)
            placement = Placement(subvertex, x, y, p)
            placements.add_placement(placement)
            progress_bar.update()
        progress_bar.end()
        return {'placements': placements}
Example #21
0
    def __call__(self, graph, machine):
        """
        :param graph: The application_graph to partition
        :type graph:\
            :py:class:`pacman.model.graphs.application.ApplicationGraph`
        :param machine:\
            The machine with respect to which to partition the application\
            graph
        :type machine: :py:class:`spinn_machine.Machine`
        :return: A machine graph
        :rtype:\
            :py:class:`pacman.model.graphs.machine.MachineGraph`
        :raise pacman.exceptions.PacmanPartitionException:\
            If something goes wrong with the partitioning
        """
        ResourceTracker.check_constraints(graph.vertices)
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=graph.vertices,
            supported_constraints=[
                MaxVertexAtomsConstraint, FixedVertexAtomsConstraint
            ],
            abstract_constraint_type=AbstractPartitionerConstraint)

        # start progress bar
        progress = ProgressBar(graph.n_vertices, "Partitioning graph vertices")
        machine_graph = MachineGraph("Machine graph for " + graph.label)
        graph_mapper = GraphMapper()
        resource_tracker = ResourceTracker(machine)

        # Partition one vertex at a time
        for vertex in progress.over(graph.vertices):
            self._partition_one_application_vertex(vertex, resource_tracker,
                                                   machine_graph, graph_mapper)

        utils.generate_machine_edges(machine_graph, graph_mapper, graph)

        return machine_graph, graph_mapper, resource_tracker.chips_used
    def __call__(self, subgraph, placements, n_keys_map, routing_paths):
        """
        Allocates routing information to the partitioned edges in a\
        partitioned graph

        :param subgraph: The partitioned graph to allocate the routing info for
        :type subgraph:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :param placements: The placements of the subvertices
        :type placements:\
                    :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map: A map between the partitioned edges and the number\
                    of keys required by the edges
        :type n_keys_map:\
                    :py:class:`pacman.model.routing_info.abstract_partitioned_edge_n_keys_map.AbstractPartitionedEdgeNKeysMap`
        :param routing_paths: the paths each partitioned edge takes to get\
                from source to destination.
        :type routing_paths:
            :py:class:`pacman.model.routing_paths.multicast_routing_paths.MulticastRoutingPaths
        :return: The routing information
        :rtype: :py:class:`pacman.model.routing_info.routing_info.RoutingInfo`,
                :py:class:`pacman.model.routing_tables.multicast_routing_table.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: If\
                   something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitioned_edges
        supported_constraints = [RequiresRoutingInfoPartitionedVertex]
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.subedges,
            supported_constraints=supported_constraints,
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each subedge and create keys from its placement
        progress_bar = ProgressBar(len(subgraph.subvertices),
                                   "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()
        for subvert in subgraph.subvertices:
            out_going_subedges = subgraph.outgoing_subedges_from_subvertex(
                subvert)
            for out_going_subedge in out_going_subedges:
                n_keys = n_keys_map.n_keys_for_partitioned_edge(
                    out_going_subedge)
                if n_keys > MAX_KEYS_SUPPORTED:
                    raise PacmanRouteInfoAllocationException(
                        "This routing info allocator can only support up to {}"
                        " keys for any given subedge; cannot therefore"
                        " allocate keys to {}, which is requesting {} keys"
                        .format(MAX_KEYS_SUPPORTED, out_going_subedge, n_keys))
                placement = placements.get_placement_of_subvertex(subvert)
                if placement is not None:
                    key = self._get_key_from_placement(placement)
                    keys_and_masks = list([BaseKeyAndMask(base_key=key,
                                                          mask=MASK)])
                    subedge_routing_info = SubedgeRoutingInfo(
                        keys_and_masks, out_going_subedge)
                    routing_infos.add_subedge_info(subedge_routing_info)
                else:
                    raise PacmanRouteInfoAllocationException(
                        "This subvertex '{}' has no placement! this should "
                        "never occur, please fix and try again."
                        .format(subvert))
                # update routing tables with entries
                routing_info_allocator_utilities.add_routing_key_entries(
                    routing_paths, subedge_routing_info, out_going_subedge,
                    routing_tables)
            progress_bar.update()
        progress_bar.end()

        return {'routing_infos': routing_infos,
                'routing_tables': routing_tables}
Example #23
0
    def __call__(self, partitioned_graph, placements, n_keys_map):
        """
        Allocates routing information to the partitioned edges in a\
        partitioned graph

        :param partitioned_graph: The partitioned graph to allocate the \
                    outing info for
        :type partitioned_graph:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :param placements: The placements of the subvertices
        :type placements:\
                    :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map: A map between the partitioned edges and the number\
                    of keys required by the edges
        :type n_keys_map:\
                    :py:class:`pacman.model.routing_info.abstract_partitioned_edge_n_keys_map.AbstractPartitionedEdgeNKeysMap`
        :return: The routing information
        :rtype: :py:class:`pacman.model.routing_info.routing_info.RoutingInfo`,
                :py:class:`pacman.model.routing_tables.multicast_routing_table.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: If\
                   something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitioned_edges
        supported_constraints = [KeyAllocatorContiguousRangeContraint]
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=partitioned_graph.partitions,
            supported_constraints=supported_constraints,
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each subedge and create keys from its placement
        progress_bar = ProgressBar(len(partitioned_graph.subvertices),
                                   "Allocating routing keys")
        routing_infos = RoutingInfo()
        for subvert in partitioned_graph.subvertices:
            partitions = partitioned_graph.\
                outgoing_edges_partitions_from_vertex(subvert)
            for partition in partitions.values():
                n_keys = n_keys_map.n_keys_for_partition(partition)
                if n_keys > MAX_KEYS_SUPPORTED:
                    raise PacmanRouteInfoAllocationException(
                        "This routing info allocator can only support up to {}"
                        " keys for any given subedge; cannot therefore"
                        " allocate keys to {}, which is requesting {} keys".
                        format(MAX_KEYS_SUPPORTED, partition, n_keys))
                placement = placements.get_placement_of_subvertex(subvert)
                if placement is not None:
                    key = self._get_key_from_placement(placement)
                    keys_and_masks = list(
                        [BaseKeyAndMask(base_key=key, mask=MASK)])
                    subedge_routing_info = PartitionRoutingInfo(
                        keys_and_masks, partition)
                    routing_infos.add_partition_info(subedge_routing_info)
                else:
                    raise PacmanRouteInfoAllocationException(
                        "This subvertex '{}' has no placement! this should "
                        "never occur, please fix and try again.".format(
                            subvert))

            progress_bar.update()
        progress_bar.end()

        return {'routing_infos': routing_infos}
    def __call__(
            self, graph, machine, plan_n_timesteps,
            preallocated_resources=None):
        """
        :param graph: The application_graph to partition
        :type graph:\
            :py:class:`pacman.model.graph.application.ApplicationGraph`
        :param machine: The machine with respect to which to partition the\
            application_graph
        :type machine: :py:class:`spinn_machine.Machine`
        :param plan_n_timesteps: number of timesteps to plan for
        :type  plan_n_timesteps: int
        :return: \
            A machine_graph of partitioned vertices and partitioned edges
        :rtype:\
            :py:class:`pacman.model.graph.machine.MachineGraph`
        :raise pacman.exceptions.PacmanPartitionException: \
            If something goes wrong with the partitioning
        """
        ResourceTracker.check_constraints(graph.vertices)
        utils.check_algorithm_can_support_constraints(
            constrained_vertices=graph.vertices,
            abstract_constraint_type=AbstractPartitionerConstraint,
            supported_constraints=[MaxVertexAtomsConstraint,
                                   SameAtomsAsVertexConstraint,
                                   FixedVertexAtomsConstraint])

        # Load the vertices and create the machine_graph to fill
        machine_graph = MachineGraph(
            label="partitioned graph for {}".format(graph.label))
        graph_mapper = GraphMapper()

        # sort out vertex's by placement constraints
        vertices = sort_vertices_by_known_constraints(graph.vertices)

        # Set up the progress
        n_atoms = 0
        for vertex in vertices:
            n_atoms += vertex.n_atoms
        progress = ProgressBar(n_atoms, "Partitioning graph vertices")

        resource_tracker = ResourceTracker(
            machine, plan_n_timesteps,
            preallocated_resources=preallocated_resources)

        # Group vertices that are supposed to be the same size
        vertex_groups = get_same_size_vertex_groups(vertices)

        # Partition one vertex at a time
        for vertex in vertices:

            # check that the vertex hasn't already been partitioned
            machine_vertices = graph_mapper.get_machine_vertices(vertex)

            # if not, partition
            if machine_vertices is None:
                self._partition_vertex(
                    vertex, plan_n_timesteps, machine_graph, graph_mapper,
                    resource_tracker, progress, vertex_groups)
        progress.end()

        generate_machine_edges(machine_graph, graph_mapper, graph)

        return machine_graph, graph_mapper, resource_tracker.chips_used
Example #25
0
    def __call__(self, subgraph, placements, n_keys_map, routing_paths):
        """
        Allocates routing information to the partitioned edges in a\
        partitioned graph

        :param subgraph: The partitioned graph to allocate the routing info for
        :type subgraph:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :param placements: The placements of the subvertices
        :type placements:\
                    :py:class:`pacman.model.placements.placements.Placements`
        :param n_keys_map: A map between the partitioned edges and the number\
                    of keys required by the edges
        :type n_keys_map:\
                    :py:class:`pacman.model.routing_info.abstract_partitioned_edge_n_keys_map.AbstractPartitionedEdgeNKeysMap`
        :param routing_paths: the paths each partitioned edge takes to get\
                from source to destination.
        :type routing_paths:
            :py:class:`pacman.model.routing_paths.multicast_routing_paths.MulticastRoutingPaths
        :return: The routing information
        :rtype: :py:class:`pacman.model.routing_info.routing_info.RoutingInfo`,
                :py:class:`pacman.model.routing_tables.multicast_routing_table.MulticastRoutingTable
        :raise pacman.exceptions.PacmanRouteInfoAllocationException: If\
                   something goes wrong with the allocation
        """

        # check that this algorithm supports the constraints put onto the
        # partitioned_edges
        supported_constraints = []
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.subedges,
            supported_constraints=supported_constraints,
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # take each subedge and create keys from its placement
        progress_bar = ProgressBar(len(subgraph.subedges),
                                   "Allocating routing keys")
        routing_infos = RoutingInfo()
        routing_tables = MulticastRoutingTables()

        for subedge in subgraph.subedges:
            destination = subedge.post_subvertex
            placement = placements.get_placement_of_subvertex(destination)
            key = self._get_key_from_placement(placement)
            keys_and_masks = list(
                [BaseKeyAndMask(base_key=key, mask=self.MASK)])
            n_keys = n_keys_map.n_keys_for_partitioned_edge(subedge)
            if n_keys > self.MAX_KEYS_SUPPORTED:
                raise exceptions.PacmanConfigurationException(
                    "Only edges which require less than {} keys are supported".
                    format(self.MAX_KEYS_SUPPORTED))

            partition_info = PartitionRoutingInfo(keys_and_masks, subedge)
            routing_infos.add_partition_info(partition_info)

            progress_bar.update()
        progress_bar.end()

        return {
            'routing_infos': routing_infos,
            'routing_tables': routing_tables
        }
    def __call__(self, graph, machine):
        """ Partition a partitionable_graph so that each subvertex will fit\
            on a processor within the machine

        :param graph: The partitionable_graph to partition
        :type graph:\
                    :py:class:`pacman.model.graph.partitionable_graph.PartitionableGraph`
        :param machine: The machine with respect to which to partition the\
                    partitionable_graph
        :type machine: :py:class:`spinn_machine.machine.Machine`
        :return: A partitioned_graph of partitioned vertices and partitioned\
                    edges
        :rtype:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :raise pacman.exceptions.PacmanPartitionException: If something\
                   goes wrong with the partitioning
        """
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=graph.vertices,
            abstract_constraint_type=AbstractPartitionerConstraint,
            supported_constraints=[PartitionerMaximumSizeConstraint,
                                   PartitionerSameSizeAsVertexConstraint])

        # Load the vertices and create the subgraph to fill
        vertices = graph.vertices
        subgraph = PartitionedGraph(
            label="partitioned graph for {}".format(graph.label))
        graph_mapper = GraphMapper(graph.label, subgraph.label)

        # sort out vertex's by constraints
        vertices = utility_calls.sort_objects_by_constraint_authority(vertices)

        # Set up the progress
        n_atoms = 0
        for vertex in vertices:
            n_atoms += vertex.n_atoms
        progress_bar = ProgressBar(n_atoms, "Partitioning graph vertices")

        resource_tracker = ResourceTracker(machine)

        # Partition one vertex at a time
        for vertex in vertices:

            # check that the vertex hasn't already been partitioned
            subverts_from_vertex = \
                graph_mapper.get_subvertices_from_vertex(vertex)

            # if not, partition
            if subverts_from_vertex is None:
                self._partition_vertex(vertex, subgraph, graph_mapper,
                                       resource_tracker, graph)
            progress_bar.update(vertex.n_atoms)
        progress_bar.end()

        partition_algorithm_utilities.generate_sub_edges(
            subgraph, graph_mapper, graph)

        results = dict()
        results['partitioned_graph'] = subgraph
        results['graph_mapper'] = graph_mapper
        return results
    def __call__(self, machine, placements):
        """ see AbstractTagAllocatorAlgorithm.allocate_tags
        """

        resource_tracker = ResourceTracker(machine)

        # Check that the algorithm can handle the constraints
        progress_bar = ProgressBar(placements.n_placements, "Allocating tags")
        placements_with_tags = list()
        for placement in placements.placements:
            utility_calls.check_algorithm_can_support_constraints(
                constrained_vertices=[placement.subvertex],
                supported_constraints=[
                    TagAllocatorRequireIptagConstraint,
                    TagAllocatorRequireReverseIptagConstraint
                ],
                abstract_constraint_type=AbstractTagAllocatorConstraint)
            if len(
                    utility_calls.locate_constraints_of_type(
                        placement.subvertex.constraints,
                        AbstractTagAllocatorConstraint)):
                placements_with_tags.append(placement)
            progress_bar.update()

        # Go through and allocate the tags
        tags = Tags()
        for placement in placements_with_tags:
            vertex = placement.subvertex

            # Get the constraint details for the tags
            (board_address, ip_tags, reverse_ip_tags) =\
                utility_calls.get_ip_tag_info(vertex.constraints)

            # Allocate the tags, first-come, first-served, using the
            # fixed placement of the vertex, and the required resources
            chips = [(placement.x, placement.y)]
            resources = vertex.resources_required
            (_, _, _, returned_ip_tags, returned_reverse_ip_tags) = \
                resource_tracker.allocate_resources(
                    resources, chips, placement.p, board_address, ip_tags,
                    reverse_ip_tags)

            # Put the allocated ip tag information into the tag object
            if returned_ip_tags is not None:
                for (tag_constraint, (board_address,
                                      tag)) in zip(ip_tags, returned_ip_tags):
                    ip_tag = IPTag(board_address, tag,
                                   tag_constraint.ip_address,
                                   tag_constraint.port,
                                   tag_constraint.strip_sdp)
                    tags.add_ip_tag(ip_tag, vertex)

            # Put the allocated reverse ip tag information into the tag object
            if returned_reverse_ip_tags is not None:
                for (tag_constraint, (board_address,
                                      tag)) in zip(reverse_ip_tags,
                                                   returned_reverse_ip_tags):
                    reverse_ip_tag = ReverseIPTag(board_address, tag,
                                                  tag_constraint.port,
                                                  placement.x, placement.y,
                                                  placement.p,
                                                  tag_constraint.sdp_port)
                    tags.add_reverse_ip_tag(reverse_ip_tag, vertex)

        progress_bar.end()
        return {'tags': tags}
    def __call__(self, subgraph, n_keys_map, routing_tables):

        # check that this algorithm supports the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.partitions,
            supported_constraints=[
                KeyAllocatorFixedMaskConstraint,
                KeyAllocatorFixedKeyAndMaskConstraint,
                KeyAllocatorContiguousRangeContraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # verify that no edge has more than 1 of a constraint ,and that
        # constraints are compatible
        routing_info_allocator_utilities.\
            check_types_of_edge_constraint(subgraph)

        routing_infos = RoutingInfo()

        # Get the partitioned edges grouped by those that require the same key
        (fixed_key_groups, fixed_mask_groups, fixed_field_groups,
         flexi_field_groups, continuous_groups, none_continuous_groups) = \
            routing_info_allocator_utilities.get_edge_groups(subgraph)

        # Even non-continuous keys will be continuous
        for group in none_continuous_groups:
            continuous_groups.add(group)

        # Go through the groups and allocate keys
        progress_bar = ProgressBar(len(subgraph.partitions),
                                   "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in fixed_key_groups:  # fixed keys groups

            # Get any fixed keys and masks from the group and attempt to
            # allocate them
            fixed_mask = None
            fixed_key_and_mask_constraint = \
                utility_calls.locate_constraints_of_type(
                    group.constraints,
                    KeyAllocatorFixedKeyAndMaskConstraint)[0]

            # attempt to allocate them
            self._allocate_fixed_keys_and_masks(
                fixed_key_and_mask_constraint.keys_and_masks, fixed_mask)

            # update the pacman data objects
            self._update_routing_objects(
                fixed_key_and_mask_constraint.keys_and_masks, routing_infos,
                group)

            continuous_groups.remove(group)

            progress_bar.update()

        for group in fixed_mask_groups:  # fixed mask groups

            # get mask and fields if need be
            fixed_mask = utility_calls.locate_constraints_of_type(
                group.constraints, KeyAllocatorFixedMaskConstraint)[0].mask

            fields = None
            if group in fixed_field_groups:
                fields = utility_calls.locate_constraints_of_type(
                    group.constraints,
                    KeyAllocatorFixedFieldConstraint)[0].fields
                fixed_field_groups.remove(group)

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                fixed_mask, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

            continuous_groups.remove(group)

            progress_bar.update()

        for group in fixed_field_groups:
            fields = utility_calls.locate_constraints_of_type(
                group.constraints, KeyAllocatorFixedFieldConstraint)[0].fields

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                None, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

            continuous_groups.remove(group)

            progress_bar.update()

        if len(flexi_field_groups) != 0:
            raise exceptions.PacmanConfigurationException(
                "MallocBasedRoutingInfoAllocator does not support FlexiField")

        # Sort the rest of the groups, using the routing tables for guidance
        # Group partitions by those which share routes in any table
        partition_groups = OrderedDict()
        routers = reversed(
            sorted(
                routing_tables.get_routers(),
                key=lambda item: len(
                    routing_tables.get_entries_for_router(item[0], item[1]))))
        for x, y in routers:

            # Find all partitions that share a route in this table
            partitions_by_route = defaultdict(OrderedSet)
            routing_table = routing_tables.get_entries_for_router(x, y)
            for partition, entry in routing_table.iteritems():
                if partition in continuous_groups:
                    entry_hash = sum([1 << i for i in entry.out_going_links])
                    entry_hash += sum(
                        [1 << (i + 6) for i in entry.out_going_processors])
                    partitions_by_route[entry_hash].add(partition)

            for entry_hash, partitions in partitions_by_route.iteritems():

                found_groups = list()
                for partition in partitions:
                    if partition in partition_groups:
                        found_groups.append(partition_groups[partition])

                if len(found_groups) == 0:

                    # If no group was found, create a new one
                    for partition in partitions:
                        partition_groups[partition] = partitions

                elif len(found_groups) == 1:

                    # If a single other group was found, merge it
                    for partition in partitions:
                        found_groups[0].add(partition)
                        partition_groups[partition] = found_groups[0]

                else:

                    # Merge the groups
                    new_group = partitions
                    for group in found_groups:
                        for partition in group:
                            new_group.add(partition)
                    for partition in new_group:
                        partition_groups[partition] = new_group

        # Sort partitions by largest group
        continuous_groups = OrderedSet(
            tuple(group) for group in partition_groups.itervalues())
        continuous_groups = reversed(
            sorted([group for group in continuous_groups],
                   key=lambda group: len(group)))

        for group in continuous_groups:
            for partition in group:
                keys_and_masks = self._allocate_keys_and_masks(
                    None, None, n_keys_map.n_keys_for_partition(partition))

                # update the pacman data objects
                self._update_routing_objects(keys_and_masks, routing_infos,
                                             partition)
                progress_bar.update()

        progress_bar.end()
        return {'routing_infos': routing_infos}
    def __call__(self, graph, machine, preallocated_resources=None):
        """
        :param graph: The application_graph to partition
        :type graph:\
            :py:class:`pacman.model.graph.application.ApplicationGraph`
        :param machine: The machine with respect to which to partition the\
            application_graph
        :type machine: :py:class:`spinn_machine.Machine`
        :return: \
            A machine_graph of partitioned vertices and partitioned edges
        :rtype:\
            :py:class:`pacman.model.graph.machine.MachineGraph`
        :raise pacman.exceptions.PacmanPartitionException: \
            If something goes wrong with the partitioning
        """
        ResourceTracker.check_constraints(graph.vertices)
        utils.check_algorithm_can_support_constraints(
            constrained_vertices=graph.vertices,
            abstract_constraint_type=AbstractPartitionerConstraint,
            supported_constraints=[MaxVertexAtomsConstraint,
                                   SameAtomsAsVertexConstraint,
                                   FixedVertexAtomsConstraint])

        # Load the vertices and create the machine_graph to fill
        machine_graph = MachineGraph(
            label="partitioned graph for {}".format(graph.label))
        graph_mapper = GraphMapper()

        # sort out vertex's by placement constraints
        vertices = placer_utils.sort_vertices_by_known_constraints(
            graph.vertices)

        # Set up the progress
        n_atoms = 0
        for vertex in vertices:
            n_atoms += vertex.n_atoms
        progress = ProgressBar(n_atoms, "Partitioning graph vertices")

        resource_tracker = ResourceTracker(
            machine, preallocated_resources=preallocated_resources)

        # Group vertices that are supposed to be the same size
        vertex_groups = partition_utils.get_same_size_vertex_groups(vertices)

        # Partition one vertex at a time
        for vertex in vertices:

            # check that the vertex hasn't already been partitioned
            machine_vertices = graph_mapper.get_machine_vertices(vertex)

            # if not, partition
            if machine_vertices is None:
                self._partition_vertex(
                    vertex, machine_graph, graph_mapper, resource_tracker,
                    progress, vertex_groups)
        progress.end()

        partition_utils.generate_machine_edges(
            machine_graph, graph_mapper, graph)

        return machine_graph, graph_mapper, resource_tracker.chips_used
Example #30
0
    def __call__(self, graph, machine):

        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=graph.vertices,
            supported_constraints=[PartitionerMaximumSizeConstraint],
            abstract_constraint_type=AbstractPartitionerConstraint)

        # start progress bar
        progress_bar = ProgressBar(len(graph.vertices),
                                   "Partitioning graph vertices")
        vertices = graph.vertices
        subgraph = PartitionedGraph(label="partitioned_graph for partitionable"
                                          "_graph {}".format(graph.label))
        graph_to_subgraph_mapper = GraphMapper(graph.label, subgraph.label)
        resource_tracker = ResourceTracker(machine)

        # Partition one vertex at a time
        for vertex in vertices:

            # Get the usage of the first atom, then assume that this
            # will be the usage of all the atoms
            requirements = vertex.get_resources_used_by_atoms(Slice(0, 1),
                                                              graph)

            # Locate the maximum resources available
            max_resources_available = \
                resource_tracker.get_maximum_constrained_resources_available(
                    vertex.constraints)

            # Find the ratio of each of the resources - if 0 is required,
            # assume the ratio is the max available
            atoms_per_sdram = self._get_ratio(
                max_resources_available.sdram.get_value(),
                requirements.sdram.get_value())
            atoms_per_dtcm = self._get_ratio(
                max_resources_available.dtcm.get_value(),
                requirements.dtcm.get_value())
            atoms_per_cpu = self._get_ratio(
                max_resources_available.cpu.get_value(),
                requirements.cpu.get_value())

            max_atom_values = [atoms_per_sdram, atoms_per_dtcm, atoms_per_cpu]

            max_atoms_constraints = utility_calls.locate_constraints_of_type(
                vertex.constraints, PartitionerMaximumSizeConstraint)
            for max_atom_constraint in max_atoms_constraints:
                max_atom_values.append(max_atom_constraint.size)

            atoms_per_core = min(max_atom_values)

            # Partition into subvertices
            counted = 0
            while counted < vertex.n_atoms:

                # Determine subvertex size
                remaining = vertex.n_atoms - counted
                if remaining > atoms_per_core:
                    alloc = atoms_per_core
                else:
                    alloc = remaining

                # Create and store new subvertex, and increment elements
                #  counted
                if counted < 0 or counted + alloc - 1 < 0:
                    raise PacmanPartitionException("Not enough resources"
                                                   " available to create"
                                                   " subvertex")

                vertex_slice = Slice(counted, counted + (alloc - 1))
                subvertex_usage = vertex.get_resources_used_by_atoms(
                    vertex_slice, graph)

                subvert = vertex.create_subvertex(
                    vertex_slice, subvertex_usage,
                    "{}:{}:{}".format(vertex.label, counted,
                                      (counted + (alloc - 1))),
                    partition_algorithm_utilities.
                    get_remaining_constraints(vertex))
                subgraph.add_subvertex(subvert)
                graph_to_subgraph_mapper.add_subvertex(
                    subvert, vertex_slice, vertex)
                counted = counted + alloc

                # update allocated resources
                resource_tracker.allocate_constrained_resources(
                    subvertex_usage, vertex.constraints)

            # update and end progress bars as needed
            progress_bar.update()
        progress_bar.end()

        partition_algorithm_utilities.generate_sub_edges(
            subgraph, graph_to_subgraph_mapper, graph)

        return {'Partitioned_graph': subgraph,
                'Graph_mapper': graph_to_subgraph_mapper}
    def __call__(self, machine_graph, n_keys_map, routing_tables):
        """
        :param MachineGraph machine_graph:
        :param AbstractMachinePartitionNKeysMap n_keys_map:
        :param MulticastRoutingTableByPartition routing_tables:
        :rtype: RoutingInfo
        """
        # check that this algorithm supports the constraints
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[
                FixedMaskConstraint, FixedKeyAndMaskConstraint,
                ContiguousKeyRangeContraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # verify that no edge has more than 1 of a constraint ,and that
        # constraints are compatible
        check_types_of_edge_constraint(machine_graph)

        routing_infos = RoutingInfo()

        # Get the edges grouped by those that require the same key
        (fixed_keys, _shared_keys, fixed_masks, fixed_fields, continuous,
         noncontinuous) = get_mulitcast_edge_groups(machine_graph)

        # Even non-continuous keys will be continuous
        continuous.extend(noncontinuous)

        # Go through the groups and allocate keys
        progress = ProgressBar(machine_graph.n_outgoing_edge_partitions,
                               "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in progress.over(fixed_keys, False):
            # Get any fixed keys and masks from the group and attempt to
            # allocate them
            fixed_mask = None
            fixed_key_and_mask_constraint = locate_constraints_of_type(
                group.constraints, FixedKeyAndMaskConstraint)[0]

            # attempt to allocate them
            self._allocate_fixed_keys_and_masks(
                fixed_key_and_mask_constraint.keys_and_masks, fixed_mask)

            # update the pacman data objects
            self._update_routing_objects(
                fixed_key_and_mask_constraint.keys_and_masks, routing_infos,
                group)
            continuous.remove(group)

        for group in progress.over(fixed_masks, False):
            # get mask and fields if need be
            fixed_mask = locate_constraints_of_type(
                group.constraints, FixedMaskConstraint)[0].mask

            fields = None
            if group in fixed_fields:
                fields = locate_constraints_of_type(
                    group.constraints, FixedKeyFieldConstraint)[0].fields
                fixed_fields.remove(group)

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                fixed_mask, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)
            continuous.remove(group)

        for group in progress.over(fixed_fields, False):
            fields = locate_constraints_of_type(
                group.constraints, FixedKeyFieldConstraint)[0].fields

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                None, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)
            continuous.remove(group)

        # Sort the rest of the groups, using the routing tables for guidance
        # Group partitions by those which share routes in any table
        partition_groups = OrderedDict()
        routers = reversed(
            sorted(
                routing_tables.get_routers(),
                key=lambda item: len(
                    routing_tables.get_entries_for_router(item[0], item[1]))))
        for x, y in routers:

            # Find all partitions that share a route in this table
            partitions_by_route = defaultdict(OrderedSet)
            routing_table = routing_tables.get_entries_for_router(x, y)
            for partition, entry in iteritems(routing_table):
                if partition in continuous:
                    entry_hash = sum(1 << i for i in entry.link_ids)
                    entry_hash += sum(1 << (i + 6)
                                      for i in entry.processor_ids)
                    partitions_by_route[entry_hash].add(partition)

            for entry_hash, partitions in iteritems(partitions_by_route):
                found_groups = list()
                for partition in partitions:
                    if partition in partition_groups:
                        found_groups.append(partition_groups[partition])

                if not found_groups:
                    # If no group was found, create a new one
                    for partition in partitions:
                        partition_groups[partition] = partitions

                elif len(found_groups) == 1:
                    # If a single other group was found, merge it
                    for partition in partitions:
                        found_groups[0].add(partition)
                        partition_groups[partition] = found_groups[0]

                else:
                    # Merge the groups
                    new_group = partitions
                    for group in found_groups:
                        for partition in group:
                            new_group.add(partition)
                    for partition in new_group:
                        partition_groups[partition] = new_group

        # Sort partitions by largest group
        continuous = list(
            OrderedSet(tuple(group) for group in itervalues(partition_groups)))

        for group in reversed(sorted(continuous, key=len)):
            for partition in progress.over(group, False):
                keys_and_masks = self._allocate_keys_and_masks(
                    None, None, n_keys_map.n_keys_for_partition(partition))

                # update the pacman data objects
                self._update_routing_objects(keys_and_masks, routing_infos,
                                             partition)

        progress.end()
        return routing_infos
Example #32
0
    def __call__(self, machine, placements):
        """ see AbstractTagAllocatorAlgorithm.allocate_tags
        """

        resource_tracker = ResourceTracker(machine)

        # Check that the algorithm can handle the constraints
        progress_bar = ProgressBar(placements.n_placements,
                                   "Allocating tags")
        placements_with_tags = list()
        for placement in placements.placements:
            utility_calls.check_algorithm_can_support_constraints(
                constrained_vertices=[placement.subvertex],
                supported_constraints=[
                    TagAllocatorRequireIptagConstraint,
                    TagAllocatorRequireReverseIptagConstraint
                ],
                abstract_constraint_type=AbstractTagAllocatorConstraint)
            if len(utility_calls.locate_constraints_of_type(
                    placement.subvertex.constraints,
                    AbstractTagAllocatorConstraint)):
                placements_with_tags.append(placement)
            progress_bar.update()

        # Go through and allocate the tags
        tags = Tags()
        for placement in placements_with_tags:
            vertex = placement.subvertex

            # Get the constraint details for the tags
            (board_address, ip_tags, reverse_ip_tags) =\
                utility_calls.get_ip_tag_info(vertex.constraints)

            # Allocate the tags, first-come, first-served, using the
            # fixed placement of the vertex, and the required resources
            chips = [(placement.x, placement.y)]
            resources = vertex.resources_required
            (_, _, _, returned_ip_tags, returned_reverse_ip_tags) = \
                resource_tracker.allocate_resources(
                    resources, chips, placement.p, board_address, ip_tags,
                    reverse_ip_tags)

            # Put the allocated ip tag information into the tag object
            if returned_ip_tags is not None:
                for (tag_constraint, (board_address, tag)) in zip(
                        ip_tags, returned_ip_tags):
                    ip_tag = IPTag(
                        board_address, tag, tag_constraint.ip_address,
                        tag_constraint.port, tag_constraint.strip_sdp)
                    tags.add_ip_tag(ip_tag, vertex)

            # Put the allocated reverse ip tag information into the tag object
            if returned_reverse_ip_tags is not None:
                for (tag_constraint, (board_address, tag)) in zip(
                        reverse_ip_tags, returned_reverse_ip_tags):
                    reverse_ip_tag = ReverseIPTag(
                        board_address, tag, tag_constraint.port, placement.x,
                        placement.y, placement.p, tag_constraint.sdp_port)
                    tags.add_reverse_ip_tag(reverse_ip_tag, vertex)

        progress_bar.end()
        return {'tags': tags}
Example #33
0
    def __call__(self, subgraph, n_keys_map, graph_mapper=None):

        # check that this algorithm supports the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=subgraph.partitions,
            supported_constraints=[
                KeyAllocatorFixedMaskConstraint,
                KeyAllocatorFixedKeyAndMaskConstraint,
                KeyAllocatorContiguousRangeContraint
            ],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # verify that no edge has more than 1 of a constraint ,and that
        # constraints are compatible
        routing_info_allocator_utilities.\
            check_types_of_edge_constraint(subgraph)

        routing_infos = RoutingInfo()

        # Get the partitioned edges grouped by those that require the same key
        (fixed_key_groups, fixed_mask_groups, fixed_field_groups,
         flexi_field_groups, continuous_groups, none_continuous_groups) = \
            routing_info_allocator_utilities.get_edge_groups(subgraph)

        # Even non-continuous keys will be continuous
        for group in none_continuous_groups:
            continuous_groups.add(group)

        # Go through the groups and allocate keys
        progress_bar = ProgressBar(len(subgraph.partitions),
                                   "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in fixed_key_groups:  # fixed keys groups

            # Get any fixed keys and masks from the group and attempt to
            # allocate them
            fixed_mask = None
            fixed_key_and_mask_constraint = \
                utility_calls.locate_constraints_of_type(
                    group.constraints,
                    KeyAllocatorFixedKeyAndMaskConstraint)[0]

            # attempt to allocate them
            self._allocate_fixed_keys_and_masks(
                fixed_key_and_mask_constraint.keys_and_masks, fixed_mask)

            # update the pacman data objects
            self._update_routing_objects(
                fixed_key_and_mask_constraint.keys_and_masks, routing_infos,
                group)

            continuous_groups.remove(group)

            progress_bar.update()

        for group in fixed_mask_groups:  # fixed mask groups

            # get mask and fields if need be
            fixed_mask = utility_calls.locate_constraints_of_type(
                group.constraints, KeyAllocatorFixedMaskConstraint)[0].mask

            fields = None
            if group in fixed_field_groups:
                fields = utility_calls.locate_constraints_of_type(
                    group.constraints,
                    KeyAllocatorFixedFieldConstraint)[0].fields
                fixed_field_groups.remove(group)

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                fixed_mask, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

            continuous_groups.remove(group)

            progress_bar.update()

        for group in fixed_field_groups:
            fields = utility_calls.locate_constraints_of_type(
                group.constraints, KeyAllocatorFixedFieldConstraint)[0].fields

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                None, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

            continuous_groups.remove(group)

            progress_bar.update()

        if len(flexi_field_groups) != 0:
            raise exceptions.PacmanConfigurationException(
                "MallocBasedRoutingInfoAllocator does not support FlexiField")

        # If there is a graph, group by source vertex and sort by vertex slice
        # (lo_atom)
        if graph_mapper is not None:
            vertex_groups = defaultdict(list)
            for partition in continuous_groups:
                vertex = graph_mapper.get_vertex_from_subvertex(
                    partition.edges[0].pre_subvertex)
                vertex_groups[vertex].append(partition)
            vertex_partitions = list()
            for vertex_group in vertex_groups.itervalues():
                sorted_partitions = sorted(
                    vertex_group,
                    key=lambda part: graph_mapper.get_subvertex_slice(
                        part.edges[0].pre_subvertex))
                vertex_partitions.extend(sorted_partitions)
            continuous_groups = vertex_partitions

        for group in continuous_groups:
            keys_and_masks = self._allocate_keys_and_masks(
                None, None, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)

        progress_bar.end()
        return {'routing_infos': routing_infos}
    def __call__(self, partitioned_graph, machine):

        # check that the algorithm can handle the constraints
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=partitioned_graph.subvertices,
            supported_constraints=[
                PlacerRadialPlacementFromChipConstraint,
                TagAllocatorRequireIptagConstraint,
                TagAllocatorRequireReverseIptagConstraint,
                PlacerChipAndCoreConstraint],
            abstract_constraint_type=AbstractPlacerConstraint)

        # Sort the vertices into those with and those without
        # placement constraints
        placements = Placements()
        constrained_vertices = list()
        unconstrained_vertices = set()
        for subvertex in partitioned_graph.subvertices:
            placement_constraints = utility_calls.locate_constraints_of_type(
                subvertex.constraints, AbstractPlacerConstraint)
            if len(placement_constraints) > 0:
                constrained_vertices.append(subvertex)
            else:
                unconstrained_vertices.add(subvertex)

        # Iterate over constrained vertices and generate placements
        progress_bar = ProgressBar(len(partitioned_graph.subvertices),
                                   "Placing graph vertices")
        resource_tracker = ResourceTracker(
            machine, self._generate_radial_chips(machine))
        for vertex in constrained_vertices:
            self._place_vertex(vertex, resource_tracker, machine, placements)
            progress_bar.update()

        while len(unconstrained_vertices) > 0:

            # Keep track of all vertices connected to the currently placed ones
            next_vertices = set()

            # Initially, add the overall most connected vertex
            max_connected_vertex = self._find_max_connected_vertex(
                unconstrained_vertices, partitioned_graph)
            next_vertices.add(max_connected_vertex)

            while len(next_vertices) > 0:

                # Find the vertex most connected to the currently placed
                # vertices
                vertex = self._find_max_connected_vertex(next_vertices,
                                                         partitioned_graph)

                # Place the vertex
                self._place_vertex(vertex, resource_tracker, machine,
                                   placements)
                progress_bar.update()
                unconstrained_vertices.remove(vertex)
                next_vertices.remove(vertex)

                # Add all vertices connected to this one to the set
                for in_edge in (partitioned_graph
                                .incoming_subedges_from_subvertex(vertex)):
                    if in_edge.pre_subvertex in unconstrained_vertices:
                        next_vertices.add(in_edge.pre_subvertex)
                for out_edge in (partitioned_graph
                                 .outgoing_subedges_from_subvertex(vertex)):
                    if out_edge.post_subvertex in unconstrained_vertices:
                        next_vertices.add(out_edge.post_subvertex)
        # finished, so stop progress bar and return placements
        progress_bar.end()
        return {'placements': placements}
    def __call__(self, machine_graph, n_keys_map, routing_tables):
        # check that this algorithm supports the constraints
        check_algorithm_can_support_constraints(
            constrained_vertices=machine_graph.outgoing_edge_partitions,
            supported_constraints=[
                FixedMaskConstraint,
                FixedKeyAndMaskConstraint,
                ContiguousKeyRangeContraint],
            abstract_constraint_type=AbstractKeyAllocatorConstraint)

        # verify that no edge has more than 1 of a constraint ,and that
        # constraints are compatible
        check_types_of_edge_constraint(machine_graph)

        routing_infos = RoutingInfo()

        # Get the edges grouped by those that require the same key
        (fixed_keys, _shared_keys, fixed_masks, fixed_fields, flexi_fields,
         continuous, noncontinuous) = \
            get_edge_groups(machine_graph, EdgeTrafficType.MULTICAST)
        if flexi_fields:
            raise PacmanConfigurationException(
                "MallocBasedRoutingInfoAllocator does not support FlexiField")

        # Even non-continuous keys will be continuous
        for group in noncontinuous:
            continuous.add(group)

        # Go through the groups and allocate keys
        progress = ProgressBar(
            machine_graph.n_outgoing_edge_partitions,
            "Allocating routing keys")

        # allocate the groups that have fixed keys
        for group in progress.over(fixed_keys, False):
            # Get any fixed keys and masks from the group and attempt to
            # allocate them
            fixed_mask = None
            fixed_key_and_mask_constraint = locate_constraints_of_type(
                group.constraints, FixedKeyAndMaskConstraint)[0]

            # attempt to allocate them
            self._allocate_fixed_keys_and_masks(
                fixed_key_and_mask_constraint.keys_and_masks, fixed_mask)

            # update the pacman data objects
            self._update_routing_objects(
                fixed_key_and_mask_constraint.keys_and_masks, routing_infos,
                group)
            continuous.remove(group)

        for group in progress.over(fixed_masks, False):
            # get mask and fields if need be
            fixed_mask = locate_constraints_of_type(
                group.constraints, FixedMaskConstraint)[0].mask

            fields = None
            if group in fixed_fields:
                fields = locate_constraints_of_type(
                    group.constraints, FixedKeyFieldConstraint)[0].fields
                fixed_fields.remove(group)

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                fixed_mask, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)
            continuous.remove(group)

        for group in progress.over(fixed_fields, False):
            fields = locate_constraints_of_type(
                group.constraints, FixedKeyFieldConstraint)[0].fields

            # try to allocate
            keys_and_masks = self._allocate_keys_and_masks(
                None, fields, n_keys_map.n_keys_for_partition(group))

            # update the pacman data objects
            self._update_routing_objects(keys_and_masks, routing_infos, group)
            continuous.remove(group)

        # Sort the rest of the groups, using the routing tables for guidance
        # Group partitions by those which share routes in any table
        partition_groups = OrderedDict()
        routers = reversed(sorted(
            routing_tables.get_routers(),
            key=lambda item: len(routing_tables.get_entries_for_router(
                item[0], item[1]))))
        for x, y in routers:

            # Find all partitions that share a route in this table
            partitions_by_route = defaultdict(OrderedSet)
            routing_table = routing_tables.get_entries_for_router(x, y)
            for partition, entry in iteritems(routing_table):
                if partition in continuous:
                    entry_hash = sum(
                        1 << i
                        for i in entry.link_ids)
                    entry_hash += sum(
                        1 << (i + 6)
                        for i in entry.processor_ids)
                    partitions_by_route[entry_hash].add(partition)

            for entry_hash, partitions in iteritems(partitions_by_route):
                found_groups = list()
                for partition in partitions:
                    if partition in partition_groups:
                        found_groups.append(partition_groups[partition])

                if not found_groups:
                    # If no group was found, create a new one
                    for partition in partitions:
                        partition_groups[partition] = partitions

                elif len(found_groups) == 1:
                    # If a single other group was found, merge it
                    for partition in partitions:
                        found_groups[0].add(partition)
                        partition_groups[partition] = found_groups[0]

                else:
                    # Merge the groups
                    new_group = partitions
                    for group in found_groups:
                        for partition in group:
                            new_group.add(partition)
                    for partition in new_group:
                        partition_groups[partition] = new_group

        # Sort partitions by largest group
        continuous = list(OrderedSet(
            tuple(group) for group in itervalues(partition_groups)))

        for group in reversed(sorted(continuous, key=len)):
            for partition in progress.over(group, False):
                keys_and_masks = self._allocate_keys_and_masks(
                    None, None, n_keys_map.n_keys_for_partition(partition))

                # update the pacman data objects
                self._update_routing_objects(
                    keys_and_masks, routing_infos, partition)

        progress.end()
        return routing_infos
    def __call__(self, graph, machine):
        """ Partition a partitionable_graph so that each subvertex will fit\
            on a processor within the machine

        :param graph: The partitionable_graph to partition
        :type graph:\
                    :py:class:`pacman.model.graph.partitionable_graph.PartitionableGraph`
        :param machine: The machine with respect to which to partition the\
                    partitionable_graph
        :type machine: :py:class:`spinn_machine.machine.Machine`
        :return: A partitioned_graph of partitioned vertices and partitioned\
                    edges
        :rtype:\
                    :py:class:`pacman.model.partitioned_graph.partitioned_graph.PartitionedGraph`
        :raise pacman.exceptions.PacmanPartitionException: If something\
                   goes wrong with the partitioning
        """
        utility_calls.check_algorithm_can_support_constraints(
            constrained_vertices=graph.vertices,
            abstract_constraint_type=AbstractPartitionerConstraint,
            supported_constraints=[PartitionerMaximumSizeConstraint,
                                   PartitionerSameSizeAsVertexConstraint])

        # Load the vertices and create the subgraph to fill
        vertices = graph.vertices
        subgraph = PartitionedGraph(
            label="partitioned graph for {}".format(graph.label))
        graph_mapper = GraphMapper(graph.label, subgraph.label)

        # sort out vertex's by constraints
        vertices = utility_calls.sort_objects_by_constraint_authority(vertices)

        # Set up the progress
        n_atoms = 0
        for vertex in vertices:
            n_atoms += vertex.n_atoms
        progress_bar = ProgressBar(n_atoms, "Partitioning graph vertices")

        resource_tracker = ResourceTracker(machine)

        # Partition one vertex at a time
        for vertex in vertices:

            # check that the vertex hasn't already been partitioned
            subverts_from_vertex = \
                graph_mapper.get_subvertices_from_vertex(vertex)

            # if not, partition
            if subverts_from_vertex is None:
                self._partition_vertex(
                    vertex, subgraph, graph_mapper, resource_tracker, graph)
            progress_bar.update(vertex.n_atoms)
        progress_bar.end()

        partition_algorithm_utilities.generate_sub_edges(
            subgraph, graph_mapper, graph)

        results = dict()
        results['partitioned_graph'] = subgraph
        results['graph_mapper'] = graph_mapper
        results['nChips'] = len(resource_tracker.keys)
        return results