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)}
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)
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
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)
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
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()
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}
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}
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
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
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
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, 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