Source code for pacman.operations.tag_allocator_algorithms.basic_tag_allocator

# Copyright (c) 2017-2019 The University of Manchester
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from spinn_utilities.progress_bar import ProgressBar
from spinn_utilities.ordered_set import OrderedSet
from spinn_machine.tags import IPTag, ReverseIPTag
from pacman.model.tags import Tags
from pacman.utilities.utility_objs import ResourceTracker

# An arbitrary range of ports from which to allocate ports to Reverse IP Tags
_BOARD_PORTS = range(17896, 18000)


[docs]class BasicTagAllocator(object): """ Basic tag allocator that goes though the boards available and applies\ the IP tags and reverse IP tags as needed. """ __slots__ = [] def __call__(self, machine, plan_n_timesteps, placements): """ see AbstractTagAllocatorAlgorithm.allocate_tags :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 :param placements: :return: """ resource_tracker = ResourceTracker(machine, plan_n_timesteps) # Keep track of ports allocated to reverse IP tags and tags that still # need a port to be allocated ports_to_allocate = dict() tags_to_allocate_ports = list() # Check that the algorithm can handle the constraints progress = ProgressBar(placements.n_placements, "Discovering tags") placements_with_tags = list() for placement in progress.over(placements.placements): self._gather_placements_with_tags(placement, placements_with_tags) # Go through and allocate the IP tags and constrained reverse IP tags tags = Tags() progress = ProgressBar(placements_with_tags, "Allocating tags") for placement in progress.over(placements_with_tags): self._allocate_tags_for_placement( placement, resource_tracker, tags, ports_to_allocate, tags_to_allocate_ports) # Finally allocate ports to the unconstrained reverse IP tags self._allocate_ports_for_reverse_ip_tags( tags_to_allocate_ports, ports_to_allocate, tags) return list(tags.ip_tags), list(tags.reverse_ip_tags), tags def _gather_placements_with_tags(self, placement, collector): if (placement.vertex.resources_required.iptags or placement.vertex.resources_required.reverse_iptags): ResourceTracker.check_constraints([placement.vertex]) collector.append(placement) def _allocate_tags_for_placement(self, placement, resource_tracker, tag_collector, ports_collector, tag_port_tasks): vertex = placement.vertex resources = vertex.resources_required # Get the constraint details for the tags (board_address, ip_tags, reverse_ip_tags) = \ ResourceTracker.get_ip_tag_info(resources, 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)] (_, _, _, 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, dest_x, dest_y)) in \ zip(ip_tags, returned_ip_tags): ip_tag = IPTag( board_address=board_address, destination_x=dest_x, destination_y=dest_y, tag=tag, ip_address=tag_constraint.ip_address, port=tag_constraint.port, strip_sdp=tag_constraint.strip_sdp, traffic_identifier=tag_constraint.traffic_identifier) tag_collector.add_ip_tag(ip_tag, vertex) if returned_reverse_ip_tags is None: return # Put the allocated reverse IP tag information into the tag object for tag_constraint, (board_address, tag) in zip( reverse_ip_tags, returned_reverse_ip_tags): if board_address not in ports_collector: ports_collector[board_address] = OrderedSet(_BOARD_PORTS) if tag_constraint.port is not None: reverse_ip_tag = ReverseIPTag( board_address, tag, tag_constraint.port, placement.x, placement.y, placement.p, tag_constraint.sdp_port) tag_collector.add_reverse_ip_tag(reverse_ip_tag, vertex) ports_collector[board_address].discard(tag_constraint.port) else: tag_port_tasks.append( (tag_constraint, board_address, tag, vertex, placement)) def _allocate_ports_for_reverse_ip_tags(self, tasks, ports, tags): for tag_constraint, board_address, tag, vertex, placement in tasks: if board_address not in ports: ports[board_address] = OrderedSet(_BOARD_PORTS) port = ports[board_address].pop(last=False) reverse_ip_tag = ReverseIPTag( board_address, tag, port, placement.x, placement.y, placement.p, tag_constraint.sdp_port) tags.add_reverse_ip_tag(reverse_ip_tag, vertex)