Source code for pacman.operations.partition_algorithms.basic_partitioner
import logging
from pacman.exceptions import PacmanPartitionException
from pacman.model.constraints.partitioner_constraints \
import AbstractPartitionerConstraint, MaxVertexAtomsConstraint
from pacman.model.graphs.common import GraphMapper, Slice
from pacman.model.graphs.machine import MachineGraph
from pacman.utilities import utility_calls
from pacman.utilities.algorithm_utilities import partition_algorithm_utilities
from pacman.utilities.utility_objs import ResourceTracker
from spinn_utilities.progress_bar import ProgressBar
logger = logging.getLogger(__name__)
[docs]class BasicPartitioner(object):
""" An basic algorithm that can partition an application graph based\
on the number of atoms in the vertices.
"""
__slots__ = []
@staticmethod
def _get_ratio(top, bottom):
if bottom == 0:
return 1.0
return top / bottom
# inherited from AbstractPartitionAlgorithm
def __call__(self, graph, machine):
"""
: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
:rtype:\
:py:class:`pacman.model.graph.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],
abstract_constraint_type=AbstractPartitionerConstraint)
# start progress bar
progress = ProgressBar(graph.n_vertices, "Partitioning graph vertices")
machine_graph = MachineGraph(
"Machine graph for {}".format(graph.label))
graph_mapper = GraphMapper()
resource_tracker = ResourceTracker(machine)
# Partition one vertex at a time
for vertex in progress.over(graph.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))
# Locate the maximum resources available
max_resources_available = \
resource_tracker.get_maximum_constrained_resources_available(
requirements, 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_cycles.get_value(),
requirements.cpu_cycles.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, MaxVertexAtomsConstraint)
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 vertices
counted = 0
while counted < vertex.n_atoms:
# Determine vertex size
remaining = vertex.n_atoms - counted
if remaining > atoms_per_core:
alloc = atoms_per_core
else:
alloc = remaining
# Create and store new vertex, and increment elements
# counted
if counted < 0 or counted + alloc - 1 < 0:
raise PacmanPartitionException(
"Not enough resources available to create vertex")
vertex_slice = Slice(counted, counted + (alloc - 1))
resources = vertex.get_resources_used_by_atoms(vertex_slice)
machine_vertex = vertex.create_machine_vertex(
vertex_slice, resources,
"{}:{}:{}".format(vertex.label, counted,
(counted + (alloc - 1))),
partition_algorithm_utilities.
get_remaining_constraints(vertex))
machine_graph.add_vertex(machine_vertex)
graph_mapper.add_vertex_mapping(
machine_vertex, vertex_slice, vertex)
counted = counted + alloc
# update allocated resources
resource_tracker.allocate_constrained_resources(
resources, vertex.constraints)
partition_algorithm_utilities.generate_machine_edges(
machine_graph, graph_mapper, graph)
return machine_graph, graph_mapper, len(resource_tracker.keys)