コード例 #1
0
    def add_edge(self, edge, graph_code):
        """ Add an edge to the edge partition.

        .. note::
            This method should only be called by the ``add_edge`` method of
            the graph that owns the partition. Calling it from anywhere else,
            even with the correct graph_code, will lead to unsupported
            inconsistency.

        :param AbstractEdge edge: the edge to add
        :param int graph_code:
            A code to check the correct graph is calling this method
        :raises PacmanInvalidParameterException:
            If the edge does not belong in this edge partition
        """
        if graph_code != self._graph_code:
            raise PacmanConfigurationException(
                "Only one graph should add edges")
        if self._graph_code is None:
            raise PacmanConfigurationException(
                "Only Graphs can add edges to partitions")

        # Check for an incompatible edge
        if not isinstance(edge, self._allowed_edge_types):
            raise PacmanInvalidParameterException(
                "edge", str(edge.__class__),
                "Edges of this graph must be one of the following types:"
                " {}".format(self._allowed_edge_types))
        self._edges.add(edge)
コード例 #2
0
    def add_edge(self, edge):
        # Check for an incompatible edge
        if not isinstance(edge, self._allowed_edge_types):
            raise PacmanInvalidParameterException(
                "edge", edge.__class__,
                "Edges of this graph must be one of the following types:"
                " {}".format(self._allowed_edge_types))

        # Check for an incompatible pre vertex
        if self._pre_vertex is None:
            self._pre_vertex = edge.pre_vertex

        elif edge.pre_vertex != self._pre_vertex:
            raise PacmanConfigurationException(
                "A partition can only contain edges with the same"
                "pre_vertex")

        # Check for an incompatible traffic type
        if self._traffic_type is None:
            self._traffic_type = edge.traffic_type
        elif edge.traffic_type != self._traffic_type:
            raise PacmanConfigurationException(
                "A partition can only contain edges with the same"
                " traffic_type")

        self._edges.add(edge)
コード例 #3
0
    def __call__(self, extended_machine, placements, allocations, constraints,
                 vertex_by_id):
        """
        :param placements:
        :param allocations:
        :param extended_machine:
        :param constraints:
        """

        # load the json files
        file_placements, core_allocations, constraints = \
            self._load_json_files(placements, allocations, constraints)

        # validate the json files against the schemas
        self._validate_file_read_data(file_placements, core_allocations,
                                      constraints)

        memory_placements = Placements()

        # process placements
        for vertex_id in file_placements:
            if str(vertex_id) not in vertex_by_id:
                if text_type(vertex_id) not in core_allocations:
                    raise PacmanConfigurationException(
                        "I don't recognise this pattern of constraints for"
                        " a vertex which does not have a placement")
                else:
                    raise PacmanConfigurationException(
                        "Failed to locate the vertex in the "
                        "graph with id {}".format(vertex_id))

            if text_type(vertex_id) in core_allocations:
                memory_placements.add_placement(
                    Placement(x=file_placements[vertex_id][0],
                              y=file_placements[vertex_id][1],
                              p=core_allocations[vertex_id][0],
                              vertex=vertex_by_id[str(vertex_id)]))
            else:
                # virtual chip or tag chip
                external_device_constraints = \
                    self._valid_constraints_for_external_device(
                        self._locate_constraints(vertex_id, constraints))
                if external_device_constraints:
                    placements.add(
                        self._make_virtual_placement(
                            extended_machine, vertex_by_id[str(vertex_id)],
                            external_device_constraints))

        # return the file format
        return memory_placements
コード例 #4
0
    def add_edge(self, edge, graph_code):
        if self._sdram_base_address is not None:
            raise PacmanConfigurationException(
                "Illegal attempt to add an edge after sdram_base_address set")

        super().check_edge(edge)

        # safety check
        if self._pre_vertex != edge.pre_vertex:
            raise PacmanConfigurationException(
                "The destination segmented SDRAM partition only accepts "
                "1 pre-vertex")

        # add
        super().add_edge(edge, graph_code)
コード例 #5
0
def sort_objects_by_constraint_authority(objects):
    """ Takes the subverts of a subgraph and orders them into a list\
        with a order based off rank on the constraint\
    :param objects: The objects to be sorted. need to have a constraints
    :type objects: iterable of soem object with constraints
    :return: A list of ordered objects
    :rtype: list of objects
    :raise None: this method does not raise any known exceptions
    """
    objects_with_rank = list()
    for current_object in objects:
        if not hasattr(current_object, "constraints"):
            raise PacmanConfigurationException(
                "the object given to the "
                "sort_objects_by_constraint_authority method does not "
                "contain constraints. Every object must have at least a "
                "max atoms per core constraint")
        max_rank_so_far = 0
        for constraint in current_object.constraints:
            # only store ranks for placer contraints and ones that are better
            # than already seen
            if (isinstance(constraint, AbstractPlacerConstraint)
                    and constraint.get_rank() >= max_rank_so_far):
                max_rank_so_far = constraint.get_rank()
        objects_with_rank.append((current_object, max_rank_so_far))

    ordered_objects = sorted(objects_with_rank,
                             key=lambda cur_item: cur_item[1],
                             reverse=True)
    return [item[0] for item in ordered_objects]
コード例 #6
0
    def _get_machine(self, url, n_chips, n_boards, total_run_time):
        """
        :param str url:
        :param int n_chips:
        :param int n_boards:
        :param int total_run_time:
        :rtype: dict
        """
        if n_boards:
            get_machine_request = requests.get(url,
                                               params={
                                                   "nBoards": n_boards,
                                                   "runTime": total_run_time
                                               })
        elif n_chips:
            get_machine_request = requests.get(url,
                                               params={
                                                   "nChips": n_chips,
                                                   "runTime": total_run_time
                                               })
        else:
            raise PacmanConfigurationException(
                "At least one of n_chips or n_boards must be provided")

        get_machine_request.raise_for_status()
        return get_machine_request.json()
コード例 #7
0
ファイル: application_graph.py プロジェクト: chanokin/PACMAN
 def add_outgoing_edge_partition(self, edge_partition):
     if self.__frozen:
         raise PacmanConfigurationException(
             "Please add partitions via simulator not directly to this "
             "graph")
     super(_FrozenApplicationGraph,
           self).add_outgoing_edge_partition(edge_partition)
コード例 #8
0
ファイル: variable_sdram.py プロジェクト: chanokin/PACMAN
 def get_total_sdram(self, n_timesteps):
     if n_timesteps is not None:
         return (self._fixed_sdram + self._per_timestep_sdram * n_timesteps)
     if self._per_timestep_sdram == 0:
         return self._fixed_sdram
     raise PacmanConfigurationException(
         "Unable to run forever with a variable SDRAM cost")
コード例 #9
0
    def _locate_destination(
            ethernet_chip_x, ethernet_chip_y, destination_class, placements):
        """ Locate destination vertex on Ethernet connected chip to send\
            fixed data to

        :param ethernet_chip_x: chip x to search
        :param ethernet_chip_y: chip y to search
        :param destination_class: the class of vertex to search for
        :param placements: the placements objects
        :return: processor ID as a int, or None if no valid processor found
        :rtype: int or None
        """
        for processor_id in range(0, Machine.MAX_CORES_PER_CHIP):
            # only check occupied processors
            if placements.is_processor_occupied(
                    ethernet_chip_x, ethernet_chip_y, processor_id):
                # verify if vertex correct one
                if isinstance(
                        placements.get_vertex_on_processor(
                            ethernet_chip_x, ethernet_chip_y, processor_id),
                        destination_class):
                    return processor_id
        raise PacmanConfigurationException(
            "no destination vertex found on Ethernet chip {}:{}".format(
                ethernet_chip_x, ethernet_chip_y))
コード例 #10
0
    def __init__(self, keys_and_masks, key_list_function=None):
        """
        :param keys_and_masks: The key and mask combinations to fix
        :type keys_and_masks: \
            iterable(:py:class:`pacman.model.routing_info.BaseKeyAndMask`)
        :param key_list_function: Optional function which will be called to\
            translate the keys_and_masks list into individual keys. If\
            missing, the keys will be generated by iterating through the \
            keys_and_masks list directly. The function parameters are:
            * An iterable of keys and masks
            * A machine edge
            * Number of keys to generate (may be None)
        :type key_list_function: iterable(\
            :py:class:`pacman.model.routing_info.BaseKeyAndMask`,\
            :py:class:`pacman.model.graphs.machine.MachineEdge`,\
            int) -> iterable(int)
        """
        for keys_and_mask in keys_and_masks:
            if not isinstance(keys_and_mask, BaseKeyAndMask):
                raise PacmanConfigurationException(
                    "the keys and masks object contains a object that is not"
                    "a key_and_mask object")

        self._keys_and_masks = keys_and_masks
        self._key_list_function = key_list_function
コード例 #11
0
ファイル: abstract_algorithm.py プロジェクト: chanokin/PACMAN
    def _get_inputs(self, inputs):
        """ Get the required and optional inputs out of the inputs

        :param dict(str,...) inputs: A dict of input type to value
        :return: A dict of parameter name to value
        :rtype: dict(str,...)
        :raises PacmanConfigurationException:
        """
        matches = dict()

        # Add required inputs, failing if they don't exist
        for required_input in self._required_inputs:
            match = required_input.get_inputs_by_name(inputs)
            if match is None:
                raise PacmanConfigurationException(
                    "Missing required input {} of type {} for algorithm {}".
                    format(required_input.name, required_input.param_types,
                           self._algorithm_id))
            matches.update(match)

        # Add optional inputs if they exist
        for optional_input in self._optional_inputs:
            match = optional_input.get_inputs_by_name(inputs)
            if match is not None:
                matches.update(match)
        return matches
コード例 #12
0
    def __locate_common_edge_type(
            self, pre_edge_types, post_edge_types, src_machine_vertex,
            dest_machine_vertex):
        """ searches the sets of edge types and finds the common one. if more\
            than one common, is biased towards the destination common and the\
            order of the list.

        :param pre_edge_types:
            the edge types the pre vertex can support for transmission
        :param post_edge_types:
            the edge types the post vertex can support for reception.
        :param MachineVertex src_machine_vertex: used for error message
        :param MachineVertex dest_machine_vertex: used for error message
        :return: MachineEdge class
        :rtype: type
        :raises PacmanConfigurationException:
            If we can't find a workable class
        """
        for post_edge_type in post_edge_types:
            if post_edge_type in pre_edge_types:
                return post_edge_type

        # if iterated over the post edge types and not found a common type.
        # Blow up coz no way these two can communicate with each other.
        raise PacmanConfigurationException(
            self.__ERROR_MESSAGE_OF_NO_COMMON_EDGE_TYPE.format(
                src_machine_vertex, dest_machine_vertex))
コード例 #13
0
def check_types_of_edge_constraint(machine_graph):
    """ Go through the graph for operations and checks that the constraints\
        are compatible.

    :param MachineGraph machine_graph: the graph to search through
    :raises PacmanConfigurationException: if a problem is found
    """
    for partition in machine_graph.outgoing_edge_partitions:
        if partition.traffic_type != EdgeTrafficType.MULTICAST:
            continue
        fixed_key = locate_constraints_of_type(
            partition.constraints, FixedKeyAndMaskConstraint)
        fixed_mask = locate_constraints_of_type(
            partition.constraints, FixedMaskConstraint)
        fixed_field = locate_constraints_of_type(
            partition.constraints, FixedKeyFieldConstraint)

        if len(fixed_key) > 1 or len(fixed_field) > 1 or len(fixed_mask) > 1:
            raise PacmanConfigurationException(
                "There are multiple constraint of the same type on partition "
                "{} starting at {}. Please fix and try again.".format(
                    partition.identifier, partition.pre_vertex))

        fixed_key = len(fixed_key) == 1
        fixed_mask = len(fixed_mask) == 1
        fixed_field = len(fixed_field) == 1

        # check for fixed key and a fixed mask. as these should have been
        # merged before now
        if fixed_key and fixed_mask:
            raise PacmanConfigurationException(
                "The partition {} starting at {} has a fixed key and fixed "
                "mask constraint. These can be merged together, but is "
                "deemed an error here".format(
                    partition.identifer, partition.pre_vertex))

        # check for a fixed key and fixed field, as these are incompatible
        if fixed_key and fixed_field:
            raise PacmanConfigurationException(
                "The partition {} starting at {} has a fixed key and fixed "
                "field constraint. These may be merge-able together, but is "
                "deemed an error here".format(
                    partition.identifer, partition.pre_vertex))

        # check that a fixed mask and fixed field have compatible masks
        if fixed_mask and fixed_field:
            _check_masks_are_correct(partition)
コード例 #14
0
def _check_allowed_elements(path, element, allowed):
    if any(
            sub.tag.split("}")[-1] not in allowed
            for sub in element.iterchildren()):
        raise PacmanConfigurationException(
            "Error in XML starting at line {} of {}: Only"
            " one of {} is allowed in {}".format(element.sourceline, path,
                                                 allowed, element.tag))
コード例 #15
0
 def _get_algorithm_data(algorithm_names, algorithm_data_objects):
     algorithms = list()
     for algorithm_name in algorithm_names:
         if algorithm_name not in algorithm_data_objects:
             raise PacmanConfigurationException(
                 "Cannot find algorithm {}".format(algorithm_name))
         algorithms.append(algorithm_data_objects[algorithm_name])
     return algorithms
コード例 #16
0
    def add_edge(self, edge, graph_code):
        # add
        super().check_edge(edge)
        super().add_edge(edge, graph_code)

        # check
        if len(self._destinations.keys()) != 1:
            raise PacmanConfigurationException(
                "The {} can only support 1 destination vertex".format(
                    self._class_name))
        if len(self._pre_vertices[edge.pre_vertex]) != 1:
            raise PacmanConfigurationException(
                "The {} only supports 1 edge from a given pre vertex.".format(
                    self._class_name))

        if self._sdram_base_address is not None:
            raise PacmanConfigurationException(
                "Illegal attempt to add an edge after sdram_base_address set")
コード例 #17
0
    def add_edge(self, edge, graph_code):
        # add
        AbstractMachineEdgePartition.check_edge(self, edge)
        AbstractMultiplePartition.add_edge(self, edge, graph_code)

        # check
        if len(self._destinations.keys()) != 1:
            raise PacmanConfigurationException(
                "The MultiSourcePartition can only support 1 destination "
                "vertex")
        if len(self._pre_vertices[edge.pre_vertex]) != 1:
            raise PacmanConfigurationException(
                "The MultiSourcePartition only supports 1 edge from a "
                "given pre vertex.")

        if self._sdram_base_address is not None:
            raise PacmanConfigurationException(
                "Illegal attempt to add an edge after sdram_base_address set")
コード例 #18
0
 def register_graph_code(self, graph_code):
     """
     Allows the graph to register its code when the partition is added
     """
     if self._graph_code is not None:
         raise PacmanConfigurationException(
             "Illegal attempt to add partition {} to a second "
             "graph".format(self))
     self._graph_code = graph_code
コード例 #19
0
    def set_max_atoms_per_core(self, max_atoms_per_core, is_fixed_atoms):
        """ sets max atoms per core for this splitter object

        :param int max_atoms_per_core: max atoms per core for this splitter.
        :param bool is_fixed_atoms: is this a hard constraint or soft.
        :raises PacmanConfigurationException:
            If the new setting clash with a previous setting
        """
        if self._is_fixed_atoms_per_core:
            # Already fixed so
            if is_fixed_atoms:
                # as new also fixed they must be the same
                if max_atoms_per_core != self._max_atoms_per_core:
                    raise PacmanConfigurationException(
                        self.FIX_ATOMS_RESET.format(
                            max_atoms_per_core, self._max_atoms_per_core))
                else:
                    return  # No change
            else:
                # as new a max make sure it is not lower than current fixed
                if max_atoms_per_core < self._max_atoms_per_core:
                    raise PacmanConfigurationException(
                        self.MAX_BELOW_FIXED.format(
                            max_atoms_per_core, self._max_atoms_per_core))
                else:
                    return  # OK to ignore the max above the fixed
        else:
            # Currently on a max so
            if is_fixed_atoms:
                # As new is fixed max sure it is not higher than max
                if max_atoms_per_core > self._max_atoms_per_core:
                    raise PacmanConfigurationException(
                        self.FIXED_ABOVE_MAX.format(
                            max_atoms_per_core, self._max_atoms_per_core))
                else:  # Set the new fixed
                    self._max_atoms_per_core = max_atoms_per_core
                    self._is_fixed_atoms_per_core = True
            else:
                # Both max so only change if new max if lower
                if max_atoms_per_core < self._max_atoms_per_core:
                    # Set the new max but leave fixed false
                    self._max_atoms_per_core = max_atoms_per_core
                else:
                    return  # Ok to Ignore a higher or same max
コード例 #20
0
 def set_governed_app_vertex(self, app_vertex):
     super().set_governed_app_vertex(app_vertex)
     if not isinstance(app_vertex, LegacyPartitionerAPI):
         for abstractmethod in LegacyPartitionerAPI._abstract_methods():
             check = getattr(app_vertex, abstractmethod, None)
             if not check:
                 raise PacmanConfigurationException(
                     self.NOT_SUITABLE_VERTEX_ERROR.format(
                         app_vertex.label, self._splitter_name,
                         abstractmethod))
             logger.warning(self.NOT_API_WARNING)
コード例 #21
0
 def add_edge(self, edge, graph_code):
     if self._sdram_size is None:
         self._sdram_size = edge.sdram_size
     elif self._sdram_size != edge.sdram_size:
         raise SDRAMEdgeSizeException(
             "The edges within the constant sdram partition {} have "
             "inconsistent memory size requests.".format(self))
     if self._sdram_base_address is None:
         AbstractSingleSourcePartition.add_edge(self, edge, graph_code)
     else:
         raise PacmanConfigurationException(
             "Illegal attempt to add an edge after sdram_base_address set")
コード例 #22
0
    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
コード例 #23
0
    def set_label(self, label):
        """ Changes the label for a vertex *not yet added* to a graph.

        :param str label: new value for the label
        :raises PacmanConfigurationException:
            If there is an attempt to change the label once the vertex has
            been added to a graph
        """
        if self._added_to_graph:
            raise PacmanConfigurationException(
                "As Labels are also IDs they can not be changed.")
        self._label = label
コード例 #24
0
    def check_edge(self, edge):
        """ check a edge traffic type.

        :param AbstractEdge edge: the edge to check
        :raises PacmanInvalidParameterException:
            If the edge does not belong in this edge partition
        """
        # Check for an incompatible traffic type
        if edge.traffic_type != self.traffic_type:
            raise PacmanConfigurationException(
                "A partition can only contain edges with the same "
                "traffic_type; trying to add a {} edge to a partition of "
                "type {}".format(edge.traffic_type, self.traffic_type))
コード例 #25
0
 def _check_allowed_elements(self, element, allowed):
     """
     :param lxml.etree._Element element:
     :param set(str) allowed:
     :raises PacmanConfigurationException:
     """
     if any(
             self.__name(sub) not in allowed
             for sub in self.__child_elems(element)):
         raise PacmanConfigurationException(
             "Error in XML starting at line {} of {}: Only"
             " one of {} is allowed in {}".format(element.sourceline,
                                                  self._xml_path, allowed,
                                                  element.tag))
コード例 #26
0
 def _get_algorithm_data(algorithm_names, algorithm_data_objects):
     """
     :param iterable(str) algorithm_names:
     :param dict(str, AbstractAlgorithm) algorithm_data_objects:
     :rtype: list(AbstractAlgorithm)
     :raises PacmanConfigurationException:
     """
     algorithms = list()
     for algorithm_name in algorithm_names:
         if algorithm_name not in algorithm_data_objects:
             raise PacmanConfigurationException(
                 "Cannot find algorithm {}".format(algorithm_name))
         algorithms.append(algorithm_data_objects[algorithm_name])
     return algorithms
コード例 #27
0
 def _allocate_partition_route(self, edge, placements, graph, n_keys_map):
     destination = edge.post_vertex
     placement = placements.get_placement_of_vertex(destination)
     keys_and_masks = list([
         BaseKeyAndMask(base_key=self._get_key_from_placement(placement),
                        mask=self.MASK)
     ])
     partition = graph.get_outgoing_edge_partition_starting_at_vertex(
         edge.pre_vertex)
     n_keys = n_keys_map.n_keys_for_partition(partition)
     if n_keys > self.MAX_KEYS_SUPPORTED:
         raise PacmanConfigurationException(
             "Only edges which require less than {} keys are"
             " supported".format(self.MAX_KEYS_SUPPORTED))
     return PartitionRoutingInfo(keys_and_masks, edge)
コード例 #28
0
ファイル: base_key_and_mask.py プロジェクト: chanokin/PACMAN
    def __init__(self, base_key, mask):
        """
        :param int base_key: The routing key
        :param int mask: The routing mask
        :raise PacmanConfigurationException:
            If key & mask != key i.e. the key is not valid for the given mask
        """
        self._base_key = base_key
        self._mask = mask

        if base_key & mask != base_key:
            raise PacmanConfigurationException(
                "This routing info is invalid as the mask {} and key {} "
                "together alters the key. This is deemed to be a error from "
                "SpiNNaker's point of view and therefore please rectify and "
                "try again".format(hex(base_key), hex(mask)))
コード例 #29
0
    def splitter(self, new_value):
        """ Sets the splitter object. Does not allow repeated settings.

        :param new_value: The new splitter object
        :type new_value:
            ~pacman.model.partitioner_interfaces.AbstractSplitterPartitioner
        :rtype: None
        """
        if self._splitter == new_value:
            return
        if self._splitter is not None:
            raise PacmanConfigurationException(
                self.SETTING_SPLITTER_ERROR_MSG.format(self._label))
        self._splitter = new_value
        self._splitter.set_governed_app_vertex(self)
        self._splitter.check_supported_constraints()
コード例 #30
0
 def _get_link_data(machine, vertex):
     if isinstance(vertex, AbstractFPGA):
         link_data = machine.get_fpga_link_with_id(
             vertex.fpga_id, vertex.fpga_link_id, vertex.board_address)
         if link_data is None:
             raise NoFPGALink(vertex)
         return link_data
     elif isinstance(vertex, AbstractSpiNNakerLink):
         link_data = machine.get_spinnaker_link_with_id(
             vertex.spinnaker_link_id, vertex.board_address)
         if link_data is None:
             raise NoSpiNNakerLink(vertex)
         return link_data
     else:
         # Ugh; this means we can't handle link data for arbitrary classes
         raise PacmanConfigurationException(
             "Unknown virtual vertex type {}".format(vertex.__class__))