Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/one_to_one_splitter' into one_to…
Browse files Browse the repository at this point in the history
…_one_splitter
  • Loading branch information
alan-stokes committed Oct 27, 2020
2 parents 8068cef + c109e9e commit 3422f83
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 68 deletions.
42 changes: 25 additions & 17 deletions pacman/model/graphs/application/application_vertex.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,34 @@ class ApplicationVertex(AbstractVertex):
"_machine_vertices",

# the splitter object associated with this app vertex
"_splitter_object"]
"_splitter"]

SETTING_SPLITTER_OBJECT_ERROR_MSG = (
SETTING_SPLITTER_ERROR_MSG = (
"The splitter object on {} has already been set, it cannot be "
"reset. Please fix and try again. ")

def __init__(self, label=None, constraints=None,
max_atoms_per_core=sys.maxsize):
max_atoms_per_core=sys.maxsize, splitter=None):
"""
:param str label: The optional name of the vertex.
:param iterable(AbstractConstraint) constraints:
The optional initial constraints of the vertex.
:param int max_atoms_per_core: The max number of atoms that can be
placed on a core, used in partitioning.
:param splitter: The splitter object needed for this vertex.
Leave as None to delegate the choice of splitter to the selector.
:type splitter None or AbstractSplitterCommon
:raise PacmanInvalidParameterException:
If one of the constraints is not valid
"""
self._splitter_object = None
# Need to set to None temporarily as add_constraint checks splitter
self._splitter = None
super(ApplicationVertex, self).__init__(label, constraints)
self._machine_vertices = OrderedSet()

# Use setter as there is extra work to do
self.splitter = splitter

# add a constraint for max partitioning
self.add_constraint(
MaxVertexAtomsConstraint(max_atoms_per_core))
Expand All @@ -69,32 +76,33 @@ def __repr__(self):
self.label, self.constraints)

@property
def splitter_object(self):
def splitter(self):
"""
:rtype: ~pacman.model.partitioner_interfaces.AbstractSplitterCommon
"""
return self._splitter_object
return self._splitter

@splitter_object.setter
def splitter_object(self, new_value):
@splitter.setter
def splitter(self, new_value):
""" sets the splitter object. Does not allow repeated settings.
:param SplitterObjectCommon new_value: the new splitter object
:rtype: None
"""
if self._splitter_object == new_value:
if self._splitter == new_value:
return
if self._splitter_object is not None:
if self._splitter is not None:
raise PacmanConfigurationException(
self.SETTING_SPLITTER_OBJECT_ERROR_MSG.format(self._label))
self._splitter_object = new_value
self._splitter_object.set_governed_app_vertex(self)
self.SETTING_SPLITTER_ERROR_MSG.format(self._label))
self._splitter = new_value
self._splitter.set_governed_app_vertex(self)
self._splitter.check_supported_constraints()

@overrides(AbstractVertex.add_constraint)
def add_constraint(self, constraint):
AbstractVertex.add_constraint(self, constraint)
if self._splitter_object is not None:
self._splitter_object.check_supported_constraints()
if self._splitter is not None:
self._splitter.check_supported_constraints()

def remember_machine_vertex(self, machine_vertex):
"""
Expand Down Expand Up @@ -156,5 +164,5 @@ def forget_machine_vertices(self):
vertex maps to.
"""
self._machine_vertices = OrderedSet()
if self._splitter_object is not None:
self._splitter_object.reset_called()
if self._splitter is not None:
self._splitter.reset_called()
36 changes: 33 additions & 3 deletions pacman/model/graphs/machine/machine_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from .machine_vertex import MachineVertex
from .machine_edge import MachineEdge
from spinn_utilities.overrides import overrides
from pacman.exceptions import PacmanInvalidParameterException
from pacman.model.graphs.graph import Graph
from pacman.model.graphs import OutgoingEdgePartition

Expand All @@ -24,7 +25,19 @@ class MachineGraph(Graph):
""" A graph whose vertices can fit on the chips of a machine.
"""

__slots__ = []
__slots__ = [
# Flags to say the application level is used so all machine vertices
# will have an application vertex
"_application_level_used",
]

MISSING_APP_VERTEX_ERROR_MESSAGE = (
"The vertex does not have an app_vertex, "
"which is required when other app_vertices exist.")

UNEXPECTED_APP_VERTEX_ERROR_MESSAGE = (
"The vertex has an app_vertex, "
"which is not allowed when others not have app_vertices.")

def __init__(self, label, application_graph=None):
"""
Expand All @@ -39,9 +52,26 @@ def __init__(self, label, application_graph=None):
MachineVertex, MachineEdge, OutgoingEdgePartition, label)
if application_graph:
application_graph.forget_machine_graph()
# Check the first vertex added
self._application_level_used = True
else:
# Must be false as there is no App_graph
self._application_level_used = False

@overrides(Graph.add_vertex)
def add_vertex(self, vertex):
super(MachineGraph, self).add_vertex(vertex)
if vertex.app_vertex:
vertex.app_vertex.remember_machine_vertex(vertex)
if self._application_level_used:
try:
vertex.app_vertex.remember_machine_vertex(vertex)
except AttributeError:
if self.n_vertices == 1:
self._application_level_used = False
else:
raise PacmanInvalidParameterException(
"vertex", vertex,
self.MISSING_APP_VERTEX_ERROR_MESSAGE)
else:
if vertex.app_vertex:
raise PacmanInvalidParameterException(
"vertex", vertex, self.UNEXPECTED_APP_VERTEX_ERROR_MESSAGE)
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class AbstractSplitterCommon(object):
"_is_fixed_atoms_per_core"
]

SETTING_SPLITTER_OBJECT_ERROR_MSG = (
SETTING_SPLITTER_ERROR_MSG = (
"The app vertex {} is already governed by this "
"{}. And so cannot govern app vertex {}."
" Please fix and try again.")
Expand Down Expand Up @@ -153,12 +153,12 @@ def set_governed_app_vertex(self, app_vertex):
return
if self._governed_app_vertex is not None:
raise PacmanConfigurationException(
self.SETTING_SPLITTER_OBJECT_ERROR_MSG.format(
self.SETTING_SPLITTER_ERROR_MSG.format(
self._governed_app_vertex, self._splitter_name,
app_vertex))
self._governed_app_vertex = app_vertex
self.check_supported_constraints()
app_vertex.splitter_object = self
app_vertex.splitter = self

def check_supported_constraints(self):
utility_calls.check_algorithm_can_support_constraints(
Expand Down
14 changes: 7 additions & 7 deletions pacman/operations/partition_algorithms/splitter_partitioner.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def __call__(

# Partition one vertex at a time
for vertex in progress.over(vertices):
vertex.splitter_object.split(resource_tracker, machine_graph)
vertex.splitter.split(resource_tracker, machine_graph)

# process edges
self.__process_machine_edges(
Expand All @@ -125,9 +125,9 @@ def order_vertices_for_dependent_splitters(vertices):
"""
dependent_vertices = OrderedDict()
for vertex in vertices:
if isinstance(vertex.splitter_object, AbstractDependentSplitter):
if isinstance(vertex.splitter, AbstractDependentSplitter):
other_app_vertex = (
vertex.splitter_object.other_splitter.governed_app_vertex)
vertex.splitter.other_splitter.governed_app_vertex)
dependent_vertices[other_app_vertex] = vertex

for main_vertex in dependent_vertices.keys():
Expand Down Expand Up @@ -183,9 +183,9 @@ def __set_same_max_atoms_to_splitters(self, app_graph):
vertex.n_atoms, fixed_n_atoms))

for other_vertex in partition_together_vertices:
other_vertex.splitter_object.set_max_atoms_per_core(
other_vertex.splitter.set_max_atoms_per_core(
max_atoms_per_core, fixed_n_atoms is not None)
vertex.splitter_object.set_max_atoms_per_core(
vertex.splitter.set_max_atoms_per_core(
max_atoms_per_core, fixed_n_atoms is not None)

def __setup_objects(
Expand Down Expand Up @@ -268,13 +268,13 @@ def __process_machine_edges(
# go through each edge
for app_edge in app_outgoing_edge_partition.edges:
src_vertices_edge_type_map = (
app_edge.pre_vertex.splitter_object.get_pre_vertices(
app_edge.pre_vertex.splitter.get_pre_vertices(
app_edge, app_outgoing_edge_partition))

# go through each pre vertices
for src_machine_vertex in src_vertices_edge_type_map:
dest_vertices_edge_type_map = (
app_edge.post_vertex.splitter_object.get_post_vertices(
app_edge.post_vertex.splitter.get_post_vertices(
app_edge, app_outgoing_edge_partition,
src_machine_vertex))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,40 @@ def test_add_duplicate_edge(self):
with self.assertRaises(PacmanAlreadyExistsException):
graph.add_edges(edges, "bar")

def test_all_have_app_vertex(self):
app_graph = ApplicationGraph("Test")
graph = MachineGraph("foo", app_graph)
app1 = SimpleTestVertex(12, "app1")
mach1 = SimpleMachineVertex("mach1", app_vertex=app1)
mach2 = SimpleMachineVertex("mach2", app_vertex=app1)
mach3 = SimpleMachineVertex("mach3", app_vertex=None)
graph.add_vertices([mach1, mach2])
with self.assertRaises(PacmanInvalidParameterException):
graph.add_vertex(mach3)

def test_none_have_app_vertex(self):
app_graph = ApplicationGraph("Test")
graph = MachineGraph("foo", app_graph)
app1 = SimpleTestVertex(12, "app1")
mach1 = SimpleMachineVertex("mach1", app_vertex=None)
mach2 = SimpleMachineVertex("mach2", app_vertex=None)
mach3 = SimpleMachineVertex("mach3", app_vertex=app1)
graph.add_vertices([mach1, mach2])
with self.assertRaises(PacmanInvalidParameterException):
graph.add_vertex(mach3)

def test_no_app_graph_no_app_vertex(self):
graph = MachineGraph("foo")
app1 = SimpleTestVertex(12, "app1")
mach1 = SimpleMachineVertex("mach1", app_vertex=app1)
mach2 = SimpleMachineVertex("mach2", app_vertex=None)
mach3 = SimpleMachineVertex("mach3", app_vertex=app1)
with self.assertRaises(PacmanInvalidParameterException):
graph.add_vertex(mach1)
graph.add_vertex(mach2)
with self.assertRaises(PacmanInvalidParameterException):
graph.add_vertex(mach3)

def test_add_edge_with_no_existing_pre_vertex_in_graph(self):
"""
test that adding a edge where the pre vertex has not been added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ def setup(self):
setup for all basic partitioner tests
"""
self.vert1 = SimpleTestVertex(10, "New AbstractConstrainedVertex 1")
self.vert1.splitter_object = SplitterSliceLegacy()
self.vert1.splitter = SplitterSliceLegacy()
self.vert2 = SimpleTestVertex(5, "New AbstractConstrainedVertex 2")
self.vert2.splitter_object = SplitterSliceLegacy()
self.vert2.splitter = SplitterSliceLegacy()
self.vert3 = SimpleTestVertex(3, "New AbstractConstrainedVertex 3")
self.vert3.splitter_object = SplitterSliceLegacy()
self.vert3.splitter = SplitterSliceLegacy()
self.edge1 = ApplicationEdge(
self.vert1, self.vert2, label="First edge")
self.edge2 = ApplicationEdge(
Expand Down Expand Up @@ -121,7 +121,7 @@ def test_partition_on_large_vertex_than_has_to_be_split(self):
"""
self.setup()
large_vertex = SimpleTestVertex(300, "Large vertex")
large_vertex.splitter_object = SplitterSliceLegacy()
large_vertex.splitter = SplitterSliceLegacy()
self.graph = ApplicationGraph("Graph with large vertex")
self.graph.add_vertex(large_vertex)
self.assertEqual(large_vertex._model_based_max_atoms_per_core, 256)
Expand All @@ -135,7 +135,7 @@ def test_partition_on_very_large_vertex_than_has_to_be_split(self):
"""
self.setup()
large_vertex = SimpleTestVertex(500, "Large vertex")
large_vertex.splitter_object = SplitterSliceLegacy()
large_vertex.splitter = SplitterSliceLegacy()
self.assertEqual(large_vertex._model_based_max_atoms_per_core, 256)
self.graph = ApplicationGraph("Graph with large vertex")
self.graph.add_vertex(large_vertex)
Expand All @@ -150,7 +150,7 @@ def test_partition_on_target_size_vertex_than_has_to_be_split(self):
self.setup()
large_vertex = SimpleTestVertex(1000, "Large vertex")
large_vertex.add_constraint(MaxVertexAtomsConstraint(10))
large_vertex.splitter_object = SplitterSliceLegacy()
large_vertex.splitter = SplitterSliceLegacy()
self.graph = ApplicationGraph("Graph with large vertex")
self.graph.add_vertex(large_vertex)
graph, _ = self.bp(self.graph, self.machine, 3000)
Expand Down Expand Up @@ -190,7 +190,7 @@ def test_partition_with_barely_sufficient_space(self):
n_neurons = 17 * 5 * 5
singular_vertex = SimpleTestVertex(n_neurons, "Large vertex",
max_atoms_per_core=1)
singular_vertex.splitter_object = SplitterSliceLegacy()
singular_vertex.splitter = SplitterSliceLegacy()
self.assertEqual(singular_vertex._model_based_max_atoms_per_core, 1)
self.graph = ApplicationGraph("Graph with large vertex")
self.graph.add_vertex(singular_vertex)
Expand Down Expand Up @@ -232,7 +232,7 @@ def test_partition_with_insufficient_space(self):
self.machine = machine_from_chips(chips)
large_vertex = SimpleTestVertex(3000, "Large vertex",
max_atoms_per_core=1)
large_vertex.splitter_object = SplitterSliceLegacy()
large_vertex.splitter = SplitterSliceLegacy()
self.assertEqual(large_vertex._model_based_max_atoms_per_core, 1)
self.graph = ApplicationGraph("Graph with large vertex")
self.graph.add_vertex(large_vertex)
Expand Down Expand Up @@ -317,7 +317,7 @@ def test_partition_with_unsupported_constraints(self):
constrained_vertex.add_constraint(
NewPartitionerConstraint("Mock constraint"))
with self.assertRaises(PacmanInvalidParameterException):
constrained_vertex.splitter_object = SplitterSliceLegacy()
constrained_vertex.splitter = SplitterSliceLegacy()

def test_partition_with_empty_graph(self):
"""
Expand Down Expand Up @@ -348,7 +348,7 @@ def test_partition_with_fixed_atom_constraints(self):
vertex = SimpleTestVertex(
sdram_per_chip * machine.n_chips,
max_atoms_per_core=2, constraints=[FixedVertexAtomsConstraint(2)])
vertex.splitter_object = SplitterSliceLegacy()
vertex.splitter = SplitterSliceLegacy()
app_graph = ApplicationGraph("Test")
app_graph.add_vertex(vertex)

Expand Down Expand Up @@ -376,7 +376,7 @@ def test_partition_with_fixed_atom_constraints_at_limit(self):
vertex = SimpleTestVertex(
sdram_per_chip * 2, max_atoms_per_core=sdram_per_chip,
constraints=[FixedVertexAtomsConstraint(sdram_per_chip // 2)])
vertex.splitter_object = SplitterSliceLegacy()
vertex.splitter = SplitterSliceLegacy()
app_graph = ApplicationGraph("Test")
app_graph.add_vertex(vertex)

Expand Down
Loading

0 comments on commit 3422f83

Please sign in to comment.