def test_sdram_links(): """ Test sdram edges which should explode """ # Create a graph machine_graph = MachineGraph("Test") # Connect a set of vertices in a chain of length 3 last_vertex = None for x in range(20): vertex = SimpleMachineVertex( resources=ResourceContainer(), label="Vertex_{}".format(x), sdram_cost=20) machine_graph.add_vertex(vertex) last_vertex = vertex for vertex in machine_graph.vertices: machine_graph.add_outgoing_edge_partition( ConstantSDRAMMachinePartition( identifier="SDRAM", pre_vertex=vertex, label="bacon")) edge = SDRAMMachineEdge(vertex, last_vertex, "bacon", app_edge=None) machine_graph.add_edge(edge, "SDRAM") n_keys_map = DictBasedMachinePartitionNKeysMap() # Do placements machine = virtual_machine(width=8, height=8) try: SpreaderPlacer()(machine_graph, machine, n_keys_map, plan_n_timesteps=1000) raise Exception("should blow up here") except PacmanException: pass
def create_machine_vertices( self, resource_tracker, machine_graph, app_graph): # slices self._post_slice = Slice( 0, int(self._governed_app_vertex.n_atoms / self.N_VERTS)) for count in range(1, self.N_VERTS): self._pre_slices.append(Slice( self._post_slice.n_atoms * count, self._post_slice.n_atoms * count + self._post_slice.n_atoms)) # mac verts self._post_vertex = ( SDRAMMachineVertex( vertex_slice=self._post_slice, label=None, constraints=None, app_vertex=self._governed_app_vertex, sdram_cost=self._governed_app_vertex.fixed_sdram_value)) resource_tracker.allocate_constrained_resources( self._post_vertex.resources_required, self._governed_app_vertex.constraints, vertices=[self._post_vertex]) machine_graph.add_vertex(self._post_vertex) for vertex_slice in self._pre_slices: pre_vertex = ( SDRAMMachineVertex( vertex_slice=vertex_slice, label=None, constraints=None, app_vertex=self._governed_app_vertex, sdram_cost=self._governed_app_vertex.fixed_sdram_value)) self._pre_vertices.append(pre_vertex) # allocate res resource_tracker.allocate_constrained_resources( pre_vertex.resources_required, self._governed_app_vertex.constraints, vertices=[pre_vertex]) # add to mac graph machine_graph.add_vertex(pre_vertex) # add outgoing edge partition to mac graph machine_graph.add_outgoing_edge_partition(self._partition_type( identifier="sdram", pre_vertices=self._pre_vertices, label="sdram")) # add edge between the two verts app and mac self._app_edge = ApplicationEdge( self._governed_app_vertex, self._governed_app_vertex) app_graph.add_edge(self._app_edge, "sdram_app") # mac add for pre_vertex in self._pre_vertices: edge = SDRAMMachineEdge( pre_vertex, self._post_vertex, label="sdram", app_edge=self._app_edge) machine_graph.add_edge(edge, "sdram") return [self._post_vertex].extend(self._pre_vertices)
def create_machine_vertices(self, resource_tracker, machine_graph, app_graph): # slices self._pre_slice = Slice(0, int(self._governed_app_vertex.n_atoms / 2)) self._post_slice = Slice( int(self._governed_app_vertex.n_atoms / 2) + 1, int(self._governed_app_vertex.n_atoms - 1)) # mac verts self._pre_vertex = (SDRAMMachineVertex( vertex_slice=self._pre_slice, label=None, constraints=None, app_vertex=self._governed_app_vertex, sdram_cost=self._governed_app_vertex.fixed_sdram_value)) self._post_vertex = (SDRAMMachineVertex( vertex_slice=self._post_slice, label=None, constraints=None, app_vertex=self._governed_app_vertex, sdram_cost=self._governed_app_vertex.fixed_sdram_value)) # allocate res resource_tracker.allocate_constrained_resources( self._pre_vertex.resources_required, self._governed_app_vertex.constraints, vertices=[self._pre_vertex]) resource_tracker.allocate_constrained_resources( self._post_vertex.resources_required, self._governed_app_vertex.constraints, vertices=[self._post_vertex]) # add to mac graph machine_graph.add_vertex(self._pre_vertex) machine_graph.add_vertex(self._post_vertex) # add outgoing edge partition to mac graph machine_graph.add_outgoing_edge_partition( self._partition_type(identifier="sdram", pre_vertex=self._pre_vertex, label="sdram")) # add edge between the two verts app and mac self._app_edge = ApplicationEdge(self._governed_app_vertex, self._governed_app_vertex) app_graph.add_edge(self._app_edge, "sdram_app") # mac add edge = SDRAMMachineEdge(self._pre_vertex, self._post_vertex, label="sdram", app_edge=self._app_edge) machine_graph.add_edge(edge, "sdram") return [self._pre_vertex, self._post_vertex]
def _do_test(self, placer): machine = virtual_machine(width=8, height=8) graph = MachineGraph("Test") plan_n_timesteps = 100 vertices = [ SimpleMachineVertex(ResourceContainer(), label="v{}".format(i), sdram_cost=20) for i in range(100) ] for vertex in vertices: graph.add_vertex(vertex) same_vertices = [ SimpleMachineVertex(ResourceContainer(), label="same{}".format(i), sdram_cost=20) for i in range(10) ] random.seed(12345) sdram_edges = list() for vertex in same_vertices: graph.add_vertex(vertex) graph.add_outgoing_edge_partition( ConstantSDRAMMachinePartition(identifier="Test", pre_vertex=vertex, label="bacon")) for _i in range(0, random.randint(1, 5)): sdram_edge = SDRAMMachineEdge(vertex, vertices[random.randint(0, 99)], label="bacon", app_edge=None) sdram_edges.append(sdram_edge) graph.add_edge(sdram_edge, "Test") n_keys_map = DictBasedMachinePartitionNKeysMap() inputs = { "MemoryExtendedMachine": machine, "MemoryMachine": machine, "MemoryMachineGraph": graph, "PlanNTimeSteps": plan_n_timesteps, "MemoryMachinePartitionNKeysMap": n_keys_map } algorithms = [placer] xml_paths = [] executor = PACMANAlgorithmExecutor(algorithms, [], inputs, [], [], [], xml_paths) executor.execute_mapping() placements = executor.get_item("MemoryPlacements") for edge in sdram_edges: pre_place = placements.get_placement_of_vertex(edge.pre_vertex) post_place = placements.get_placement_of_vertex(edge.post_vertex) assert pre_place.x == post_place.x assert pre_place.y == post_place.y
def _do_test(self, placer): machine = virtual_machine(width=8, height=8) graph = MachineGraph("Test") vertices = [ MockMachineVertex(ResourceContainer(), label="v{}".format(i), sdram_requirement=20) for i in range(100) ] for vertex in vertices: graph.add_vertex(vertex) same_vertices = [ MockMachineVertex(ResourceContainer(), label="same{}".format(i), sdram_requirement=20) for i in range(10) ] random.seed(12345) sdram_edges = list() for vertex in same_vertices: graph.add_vertex(vertex) graph.add_outgoing_edge_partition( ConstantSDRAMMachinePartition(identifier="Test", pre_vertex=vertex, label="bacon")) for _i in range(0, random.randint(1, 5)): sdram_edge = SDRAMMachineEdge(vertex, vertices[random.randint(0, 99)], label="bacon", app_edge=None) sdram_edges.append(sdram_edge) graph.add_edge(sdram_edge, "Test") n_keys_map = DictBasedMachinePartitionNKeysMap() if placer == "ConnectiveBasedPlacer": placements = connective_based_placer(graph, machine, None) elif placer == "OneToOnePlacer": placements = one_to_one_placer(graph, machine, None) elif placer == "RadialPlacer": placements = radial_placer(graph, machine, None) elif placer == "SpreaderPlacer": placements = spreader_placer(graph, machine, n_keys_map, None) else: raise NotImplementedError(placer) for edge in sdram_edges: pre_place = placements.get_placement_of_vertex(edge.pre_vertex) post_place = placements.get_placement_of_vertex(edge.post_vertex) assert pre_place.x == post_place.x assert pre_place.y == post_place.y
def test_at_vertex_methods(self): graph = MachineGraph("foo") mach1 = MockMachineVertex("mach1", sdram_requirement=0) mach2 = MockMachineVertex("mach2", sdram_requirement=0) mach3 = MockMachineVertex("mach3", sdram_requirement=0) mach4 = SimpleMachineVertex("mach4") graph.add_vertices([mach1, mach2, mach3, mach4]) # Add partition then edge part_m_1 = MulticastEdgePartition(mach1, "spikes") graph.add_outgoing_edge_partition(part_m_1) edge_m_11 = MachineEdge(mach1, mach2, traffic_type=EdgeTrafficType.MULTICAST) graph.add_edge(edge_m_11, "spikes") # check clear error it you add the edge again with self.assertRaises(PacmanAlreadyExistsException): graph.add_edge(edge_m_11, "spikes") self.assertIn(edge_m_11, part_m_1.edges) edge_m_12 = MachineEdge(mach1, mach3, traffic_type=EdgeTrafficType.MULTICAST) graph.add_edge(edge_m_12, "spikes") edge_m_21 = MachineEdge(mach3, mach4, traffic_type=EdgeTrafficType.MULTICAST) graph.add_edge(edge_m_21, "spikes") part_m_2 = graph.get_outgoing_partition_for_edge(edge_m_21) edge_f_1 = MachineEdge(mach1, mach3, traffic_type=EdgeTrafficType.FIXED_ROUTE) graph.add_edge(edge_f_1, "Control") part_f = graph.get_outgoing_partition_for_edge(edge_f_1) part_s_1 = ConstantSDRAMMachinePartition("ram", mach1, "ram1") graph.add_outgoing_edge_partition(part_s_1) edge_s_11 = SDRAMMachineEdge(mach1, mach2, "s1") graph.add_edge(edge_s_11, "ram") edge_s_12 = SDRAMMachineEdge(mach1, mach3, "s2") graph.add_edge(edge_s_12, "ram") starting_at_mach1 = list( graph.get_outgoing_edge_partitions_starting_at_vertex(mach1)) self.assertIn(part_m_1, starting_at_mach1) self.assertIn(part_f, starting_at_mach1) self.assertIn(part_s_1, starting_at_mach1) self.assertEqual(3, len(starting_at_mach1)) starting_at_mach3 = list( graph.get_outgoing_edge_partitions_starting_at_vertex(mach3)) self.assertIn(part_m_2, starting_at_mach3) self.assertEqual(1, len(starting_at_mach3)) starting_at_mach4 = list( graph.get_outgoing_edge_partitions_starting_at_vertex(mach4)) self.assertEqual(0, len(starting_at_mach4)) ending_at_mach2 = list( graph.get_edge_partitions_ending_at_vertex(mach2)) self.assertIn(part_m_1, ending_at_mach2) self.assertIn(part_s_1, ending_at_mach2) self.assertEqual(2, len(ending_at_mach2)) ending_at_mach3 = list( graph.get_edge_partitions_ending_at_vertex(mach3)) self.assertIn(part_m_1, ending_at_mach3) self.assertIn(part_f, ending_at_mach3) self.assertIn(part_s_1, ending_at_mach3) self.assertEqual(3, len(ending_at_mach3)) ending_at_mach1 = list( graph.get_edge_partitions_ending_at_vertex(mach1)) self.assertEqual(0, len(ending_at_mach1))
def create_machine_vertices( self, resource_tracker, machine_graph, app_graph): # slices self._post_slice = Slice( 0, int(self._governed_app_vertex.n_atoms / self.N_VERTS)) for count in range(1, self.N_VERTS): self._pre_slices.add(Slice( self._post_slice.n_atoms * count, self._post_slice.n_atoms * count + self._post_slice.n_atoms)) # mac verts self._post_vertex = ( SDRAMMachineVertex( vertex_slice=self._post_slice, label=None, constraints=None, app_vertex=self._governed_app_vertex, sdram_cost=self._governed_app_vertex.fixed_sdram_value)) resource_tracker.allocate_constrained_resources( self._post_vertex.resources_required, self._governed_app_vertex.constraints) machine_graph.add_vertex(self._post_vertex) for vertex_slice in self._pre_slices: pre_vertex = ( SDRAMMachineVertex( vertex_slice=vertex_slice, label=None, constraints=None, app_vertex=self._governed_app_vertex, sdram_cost=self._governed_app_vertex.fixed_sdram_value)) self._pre_vertices.add(pre_vertex) # allocate res resource_tracker.allocate_constrained_resources( pre_vertex.resources_required, self._governed_app_vertex.constraints) # add to mac graph machine_graph.add_vertex(pre_vertex) # add outgoing edge partition to mac graph if self._other_splitter is not None: total_pre_verts = list() total_pre_verts.extend(self._pre_vertices) for incoming_edge in app_graph.get_edges_ending_at_vertex( self._governed_app_vertex): if (incoming_edge.pre_vertex.splitter == self._other_splitter): outgoing_edge_partition = ( app_graph.get_outgoing_partition_for_edge( incoming_edge)) total_pre_verts.extend( self._other_splitter.get_out_going_vertices( incoming_edge, outgoing_edge_partition)) machine_graph.add_outgoing_edge_partition(self._partition_type( identifier="sdram", pre_vertices=total_pre_verts, label="sdram")) # add edge between the two verts app and mac self._app_edge = ApplicationEdge( self._governed_app_vertex, self._governed_app_vertex) app_graph.add_edge(self._app_edge, "sdram_app") # mac add for pre_vertex in self._pre_vertices: edge = SDRAMMachineEdge( pre_vertex, self._post_vertex, label="sdram", app_edge=self._app_edge) machine_graph.add_edge(edge, "sdram") return [self._post_vertex].extend(self._pre_vertices)
def create_machine_vertices(self, resource_tracker, machine_graph): app_vertex = self._governed_app_vertex label = app_vertex.label constraints = get_remaining_constraints(app_vertex) # Structural plasticity can only be run on a single synapse core if (isinstance(app_vertex.synapse_dynamics, AbstractSynapseDynamicsStructural) and self.__n_synapse_vertices != 1): raise SynapticConfigurationException( "The current implementation of structural plasticity can only" " be run on a single synapse core. Please ensure the number" " of synapse cores is set to 1") # Do some checks to make sure everything is likely to fit atoms_per_core = min(app_vertex.get_max_atoms_per_core(), app_vertex.n_atoms) n_synapse_types = app_vertex.neuron_impl.get_n_synapse_types() if (get_n_bits(atoms_per_core) + get_n_bits(n_synapse_types) + get_n_bits(self.__get_max_delay)) > MAX_RING_BUFFER_BITS: raise SynapticConfigurationException( "The combination of the number of neurons per core ({}), " "the number of synapse types ({}), and the maximum delay per " "core ({}) will require too much DTCM. Please reduce one or " "more of these values.".format(atoms_per_core, n_synapse_types, self.__get_max_delay)) self.__neuron_vertices = list() self.__synapse_vertices = list() self.__synapse_verts_by_neuron = defaultdict(list) incoming_direct_poisson = self.__handle_poisson_sources( label, machine_graph) # Work out the ring buffer shifts based on all incoming things rb_shifts = app_vertex.get_ring_buffer_shifts( app_vertex.incoming_projections) weight_scales = app_vertex.get_weight_scales(rb_shifts) # Get resources for synapses independent_synapse_sdram = self.__independent_synapse_sdram() proj_dependent_sdram = self.__proj_dependent_synapse_sdram( app_vertex.incoming_projections) for index, vertex_slice in enumerate(self.__get_fixed_slices()): # Find the maximum number of cores on any chip available max_crs = resource_tracker.get_maximum_cores_available_on_a_chip() if max_crs < (self.__n_synapse_vertices + 1): raise ConfigurationException( "No chips remaining with enough cores for" f" {self.__n_synapse_vertices} synapse cores and a neuron" " core") max_crs -= self.__n_synapse_vertices + 1 # Create the neuron vertex for the slice neuron_vertex, neuron_resources = self.__add_neuron_core( vertex_slice, label, index, rb_shifts, weight_scales, machine_graph, constraints) # Keep track of synapse vertices for each neuron vertex and # resources used by each core (neuron core is added later) synapse_vertices = list() self.__synapse_verts_by_neuron[neuron_vertex] = synapse_vertices all_resources = [] # Add the first vertex synapse_references, syn_label = self.__add_lead_synapse_core( vertex_slice, independent_synapse_sdram, proj_dependent_sdram, label, rb_shifts, weight_scales, all_resources, machine_graph, synapse_vertices, neuron_vertex, constraints) # Do the remaining synapse cores for i in range(1, self.__n_synapse_vertices): self.__add_shared_synapse_core(syn_label, i, vertex_slice, synapse_references, all_resources, machine_graph, synapse_vertices, neuron_vertex, constraints) # Add resources for Poisson vertices up to core limit poisson_vertices = incoming_direct_poisson[vertex_slice] remaining_poisson_vertices = list() added_poisson_vertices = list() for poisson_vertex, poisson_edge in poisson_vertices: if max_crs <= 0: remaining_poisson_vertices.append(poisson_vertex) self.__add_poisson_multicast(poisson_vertex, synapse_vertices, machine_graph, poisson_edge) else: all_resources.append( (poisson_vertex.resources_required, [])) added_poisson_vertices.append(poisson_vertex) max_crs -= 1 if remaining_poisson_vertices: logger.warn( f"Vertex {label} is using multicast for" f" {len(remaining_poisson_vertices)} one-to-one Poisson" " sources as not enough cores exist to put them on the" " same chip") # Create an SDRAM edge partition sdram_label = "SDRAM {} Synapses-->Neurons:{}-{}".format( label, vertex_slice.lo_atom, vertex_slice.hi_atom) source_vertices = added_poisson_vertices + synapse_vertices sdram_partition = SourceSegmentedSDRAMMachinePartition( SYNAPSE_SDRAM_PARTITION_ID, sdram_label, source_vertices) machine_graph.add_outgoing_edge_partition(sdram_partition) neuron_vertex.set_sdram_partition(sdram_partition) # Add SDRAM edges for synapse vertices for source_vertex in source_vertices: edge_label = "SDRAM {}-->{}".format(source_vertex.label, neuron_vertex.label) machine_graph.add_edge( SDRAMMachineEdge(source_vertex, neuron_vertex, edge_label), SYNAPSE_SDRAM_PARTITION_ID) source_vertex.set_sdram_partition(sdram_partition) # Add SDRAM edge requirements to the neuron SDRAM, as the resource # tracker will otherwise try to add another core for it extra_sdram = MultiRegionSDRAM() extra_sdram.merge(neuron_resources.sdram) extra_sdram.add_cost( len(extra_sdram.regions) + 1, sdram_partition.total_sdram_requirements()) neuron_resources_plus = ResourceContainer( sdram=extra_sdram, dtcm=neuron_resources.dtcm, cpu_cycles=neuron_resources.cpu_cycles, iptags=neuron_resources.iptags, reverse_iptags=neuron_resources.reverse_iptags) all_resources.append((neuron_resources_plus, constraints)) # Allocate all the resources to ensure they all fit resource_tracker.allocate_constrained_group_resources( all_resources) return True