def _get_v(self): """ get the voltage from the vertex :return: the voltages """ # check that we're ina state to get voltages if isinstance(self._population._vertex, AbstractVRecordable): if not self._population._vertex.is_recording_v(): raise fec_excceptions.ConfigurationException( "This population has not been set to record v") else: raise fec_excceptions.ConfigurationException( "This population has not got the capability to record v") if not globals_variables.get_simulator().has_ran: logger.warn("The simulation has not yet run, therefore v cannot" " be retrieved, hence the list will be empty") return numpy.zeros((0, 3)) if globals_variables.get_simulator().use_virtual_board: logger.warn( "The simulation is using a virtual machine and so has not" " truly ran, hence the list will be empty") return numpy.zeros((0, 3)) # assuming we got here, everything is ok, so we should go get the # voltages return self._population._vertex.get_v( globals_variables.get_simulator().no_machine_time_steps, globals_variables.get_simulator().placements, globals_variables.get_simulator().graph_mapper, globals_variables.get_simulator().buffer_manager, globals_variables.get_simulator().machine_time_step)
def getSpikes(self, compatible_output=False, gather=True): """ Return a 2-column numpy array containing cell ids and spike times for\ recorded cells. """ if not gather: logger.warn("Spynnaker only supports gather = true, will " " execute as if gather was true anyhow") if isinstance(self._vertex, AbstractSpikeRecordable): if not self._vertex.is_recording_spikes(): raise exceptions.ConfigurationException( "This population has not been set to record spikes") else: raise exceptions.ConfigurationException( "This population has not got the capability to record spikes") if not self._spinnaker.has_ran: logger.warn( "The simulation has not yet run, therefore spikes cannot" " be retrieved, hence the list will be empty") return numpy.zeros((0, 2)) if self._spinnaker.use_virtual_board: logger.warn( "The simulation is using a virtual machine and so has not" " truly ran, hence the list will be empty") return numpy.zeros((0, 2)) spikes = self._vertex.get_spikes(self._spinnaker.placements, self._spinnaker.graph_mapper, self._spinnaker.buffer_manager) return spikes
def __call__(self, transceiver, has_ran, placements=None, core_subsets=None): if not has_ran: raise exceptions.ConfigurationException( "The simulation needs to have tried to run before asking for" "iobuf. Please fix and try again") if core_subsets is not None: io_buffers, error_entries, warn_entries =\ self._run_for_core_subsets( core_subsets, transceiver) elif placements is not None: io_buffers, error_entries, warn_entries =\ self._run_for_placements( placements, transceiver) else: raise exceptions.ConfigurationException( "The FrontEndCommonIOBufExtractor requires either a placements" " object or a core sets object to be able to execute") return { 'io_buffers': io_buffers, 'error_entries': error_entries, 'warn_entries': warn_entries }
def get_v(self, gather=True, compatible_output=False): """ Return a 3-column numpy array containing cell ids, time, and V_m for recorded cells. :param gather: not used - inserted to match PyNN specs :type gather: bool :param compatible_output: not used - inserted to match PyNN specs :type compatible_output: bool """ if isinstance(self._vertex, AbstractVRecordable): if not self._vertex.is_recording_v(): raise exceptions.ConfigurationException( "This population has not been set to record v") else: raise exceptions.ConfigurationException( "This population has not got the capability to record v") if not self._spinnaker.has_ran: logger.warn("The simulation has not yet run, therefore v cannot" " be retrieved, hence the list will be empty") return numpy.zeros((0, 3)) if self._spinnaker.use_virtual_board: logger.warn( "The simulation is using a virtual machine and so has not" " truly ran, hence the list will be empty") return numpy.zeros((0, 3)) return self._vertex.get_v(self._spinnaker.no_machine_time_steps, self._spinnaker.placements, self._spinnaker.graph_mapper, self._spinnaker.buffer_manager)
def _get_gsyn_inhibitory(self): """ get the gsyn inhibitory values from the vertex :return: the gsyn inhibitory values """ if isinstance(self._population._vertex, AbstractGSynInhibitoryRecordable): if not self._population._vertex.is_recording_gsyn_inhibitory(): raise fec_excceptions.ConfigurationException( "This population has not been set to record gsyn " "inhibitory") else: raise fec_excceptions.ConfigurationException( "This population has not got the capability to record gsyn " "inhibitory") if not globals_variables.get_simulator().has_ran: logger.warn( "The simulation has not yet run, therefore gsyn inhibitory " "cannot be retrieved, hence the list will be empty") return numpy.zeros((0, 4)) if globals_variables.get_simulator().use_virtual_board: logger.warn( "The simulation is using a virtual machine and so has not" " truly ran, hence the list will be empty") return numpy.zeros((0, 4)) return self._population._vertex.get_gsyn_inhibitory( globals_variables.get_simulator().no_machine_time_steps, globals_variables.get_simulator().placements, globals_variables.get_simulator().graph_mapper, globals_variables.get_simulator().buffer_manager, globals_variables.get_simulator().machine_time_step)
def __call__(self, executable_targets, app_id, transceiver, loaded_application_data_token): """ Go through the executable targets and load each binary to \ everywhere and then send a start request to the cores that \ actually use it """ if not loaded_application_data_token: raise exceptions.ConfigurationException( "The token for having loaded the application data token is set" " to false and therefore I cannot run. Please fix and try " "again") progress_bar = ProgressBar(executable_targets.total_processors, "Loading executables onto the machine") for executable_target_key in executable_targets.binaries: file_reader = FileDataReader(executable_target_key) core_subset = executable_targets.get_cores_for_binary( executable_target_key) statinfo = os.stat(executable_target_key) size = statinfo.st_size # TODO there is a need to parse the binary and see if its # ITCM and DTCM requirements are within acceptable params for # operating on spinnaker. Currently there just a few safety # checks which may not be accurate enough. if size > constants.MAX_SAFE_BINARY_SIZE: logger.warn( "The size of {} is large enough that its" " possible that the binary may be larger than what is" " supported by spinnaker currently. Please reduce the" " binary size if it starts to behave strangely, or goes" " into the WDOG state before starting.".format( executable_target_key)) if size > constants.MAX_POSSIBLE_BINARY_SIZE: raise exceptions.ConfigurationException( "The size of {} is too large and therefore" " will very likely cause a WDOG state. Until a more" " precise measurement of ITCM and DTCM can be produced" " this is deemed as an error state. Please reduce the" " size of your binary or circumvent this error check.". format(executable_target_key)) transceiver.execute_flood(core_subset, file_reader, app_id, size) acutal_cores_loaded = 0 for chip_based in core_subset.core_subsets: for _ in chip_based.processor_ids: acutal_cores_loaded += 1 progress_bar.update(amount_to_add=acutal_cores_loaded) progress_bar.end() return {"LoadBinariesToken": True}
def record(variables, source, filename, sampling_interval=None, annotations=None): raise exceptions.ConfigurationException( "You cannot call record until you have called setup.")
def reserve_buffer_regions( self, spec, state_region, buffer_regions, region_sizes): """ Reserves the region for recording and the region for storing the\ end state of the buffering :param spec: The data specification to reserve the region in :param state_region: The id of the region to use as the end state\ region :param buffer_regions: The regions ids to reserve for buffering :param region_sizes: The sizes of the regions to reserve """ if len(buffer_regions) != len(region_sizes): raise exceptions.ConfigurationException( "The number of buffer regions must match the number of" " regions sizes") for (buffer_region, region_size) in zip( buffer_regions, region_sizes): if region_size > 0: self._buffered_regions.append(buffer_region) spec.reserve_memory_region( region=buffer_region, size=region_size, label="RECORDING_REGION_{}".format(buffer_region), empty=True) spec.reserve_memory_region( region=state_region, size=EndBufferingState.size_of_region(len(buffer_regions)), label='BUFFERED_OUT_STATE', empty=True) self._buffered_state_region = state_region
def _calculate_power_down_cost( self, time, machine, machine_allocation_controller, version, n_frames): """ calculate power down costs :param time: time powered down :param n_frames: number of frames used by this machine :return: power in jules """ # if spalloc or hbp if machine_allocation_controller is not None: return (time * n_frames * self.JULES_PER_MILLISECOND_FOR_FRAME_IDLE_COST) # if 48 chip if version == 5 or version == 4: return ( time * self.JULES_PER_MILLISECOND_FOR_BOXED_48_CHIP_FRAME_IDLE_COST) # if 4 chip if version == 3 or version == 2: return (len(list(machine.chips)) * time * self.JULES_PER_MILLISECOND_PER_IDLE_CHIP) # boom raise exceptions.ConfigurationException("dont know what to do here")
def _turn_on_recording(self, variable, sampling_interval, indexes): rate = self._compute_rate(sampling_interval) if self._sampling_rates[variable] == 0: self._sampling_rates[variable] = rate elif rate != self._sampling_rates[variable]: msg = "Current implementation does not support multiple " \ "sampling_intervals for {} on one population. " \ .format(variable) raise fec_excceptions.ConfigurationException(msg) # else rate not changed so no action if indexes is None: # previous recording indexes does not matter as now all (None) self._indexes[variable] = None else: self.check_indexes(indexes) if self._indexes[variable] is None: # just use the new indexes self._indexes[variable] = indexes else: # merge the two indexes self._indexes[variable] = \ list(set(self._indexes[variable] + indexes)) self._indexes[variable].sort()
def _turn_off_recording(self, variable, sampling_interval, remove_indexes): if self._sampling_rates[variable] == 0: # Already off so ignore other parameters return if remove_indexes is None: # turning all off so ignoring sampling interval self._sampling_rates[variable] = 0 self._indexes[variable] = None return # No good reason to specify_interval when turning off if sampling_interval is not None: rate = self._compute_rate(sampling_interval) # But if they do make sure it is the same as before if rate != self._sampling_rates[variable]: msg = "Illegal sampling_interval parameter while turning " \ "off recording" raise fec_excceptions.ConfigurationException(msg) if self._indexes[variable] is None: # start with all indexes self._indexes[variable] = range(self._n_neurons) # remove the indexes not recording self._indexes[variable] = \ [index for index in self._indexes[variable] if index not in remove_indexes] # Check is at least one index still recording if len(self._indexes[variable]) == 0: self._sampling_rates[variable] = 0 self._indexes[variable] = None
def is_recording(self, variable): try: return self._sampling_rates[variable] > 0 except KeyError: msg = "Variable {} is not supported. Supported variables are {}" \ "".format(variable, self.get_recordable_variables()) raise fec_excceptions.ConfigurationException(msg)
def get_data(self, transceiver, placement, n_machine_time_steps): data = list() # Get the data region base address where results are stored for the # core record_region_base_address = \ helpful_functions.locate_memory_region_for_placement( placement, self.DATA_REGIONS.RESULTS.value, transceiver) # find how many bytes are needed to be read number_of_bytes_to_read = str(transceiver.read_memory( placement.x, placement.y, record_region_base_address, 4)) number_of_bytes_to_read = \ struct.unpack("<I", number_of_bytes_to_read)[0] # read the bytes if number_of_bytes_to_read != (n_machine_time_steps * 4): raise exceptions.ConfigurationException( "number of bytes seems wrong") else: raw_data = str(transceiver.read_memory( placement.x, placement.y, record_region_base_address + 4, number_of_bytes_to_read)) # convert to ints elements = struct.unpack( "<{}I".format(n_machine_time_steps), raw_data) for element in elements: if element == 0: data.append(False) else: data.append(True) # return the data return data
def __call__(self, partitioned_graph, placements, buffer_manager, ran_token): if not ran_token: raise exceptions.ConfigurationException( "The ran token has not been set") # Count the regions to be read n_regions_to_read = 0 for vertex in partitioned_graph.subvertices: if isinstance(vertex, AbstractReceiveBuffersToHost): n_regions_to_read += len(vertex.get_buffered_regions()) progress_bar = ProgressBar(n_regions_to_read, "Extracting buffers from the last run") # Read back the regions for vertex in partitioned_graph.subvertices: if isinstance(vertex, AbstractReceiveBuffersToHost): placement = placements.get_placement_of_subvertex(vertex) state_region = vertex.get_buffered_state_region() for region in vertex.get_buffered_regions(): buffer_manager.get_data_for_vertex(placement, region, state_region) progress_bar.update() progress_bar.end()
def set_model_based_max_atoms_per_core(self, new_value): if hasattr(self._vertex, "set_model_max_atoms_per_core"): self._vertex.set_model_max_atoms_per_core(new_value) else: raise exceptions.ConfigurationException( "This population does not support its max_atoms_per_core " "variable being adjusted by the end user. Sorry")
def convert_param_to_numpy(param, no_atoms): """ Convert parameters into numpy arrays :param param: the param to convert :param no_atoms: the number of atoms available for conversion of param :return numpy.array: the converted param in whatever format it was given """ # Deal with random distributions by generating values if globals_variables.get_simulator().is_a_pynn_random(param): if no_atoms > 1: return numpy.asarray(param.next(n=no_atoms), dtype="float") # numpy reduces a single valued array to a single value, so enforce # that it is an array return numpy.array([param.next(n=no_atoms)], dtype="float") # Deal with a single value by exploding to multiple values if not hasattr(param, '__iter__'): return numpy.array([param] * no_atoms, dtype="float") # Deal with multiple values, but not the correct number of them if len(param) != no_atoms: raise exceptions.ConfigurationException( "The number of params does not equal with the number of atoms in" " the vertex") # Deal with the correct number of multiple values return numpy.array(param, dtype="float")
def get_gsyn(self, gather=True, compatible_output=False): """ Return a 3-column numpy array containing cell ids and synaptic conductances for recorded cells. """ if self._gsyn is None: if not self._vertex.record_gsyn: raise exceptions.ConfigurationException( "This population has not been set to record gsyn. " "Therefore gsyn cannot be retrieved. Please set this " "vertex to record gsyn before running this command.") if not self._spinnaker.has_ran: raise local_exceptions.SpynnakerException( "The simulation has not yet run, therefore gsyn cannot" " be retrieved. Please execute the simulation before" " running this command") timer = None if conf.config.getboolean("Reports", "outputTimesForSections"): timer = Timer() timer.start_timing() self._gsyn = self._vertex.get_gsyn( has_ran=self._spinnaker.has_ran, txrx=self._spinnaker.transceiver, placements=self._spinnaker.placements, machine_time_step=self._spinnaker.machine_time_step, graph_mapper=self._spinnaker.graph_mapper, compatible_output=compatible_output, runtime=self._spinnaker._runtime) if conf.config.getboolean("Reports", "outputTimesForSections"): timer.take_sample() return self._gsyn
def getSpikes(self, compatible_output=False, gather=True): """ Return a 2-column numpy array containing cell ids and spike times for recorded cells. This is read directly from the memory for the board. """ if self._spikes is None: if not gather: logger.warn("Spynnaker only supports gather = true, will " " execute as if gather was true anyhow") timer = None if not self._vertex.record: raise exceptions.ConfigurationException( "This population has not been set to record spikes. " "Therefore spikes cannot be retrieved. Please set this " "vertex to record spikes before running this command.") if not self._spinnaker.has_ran: raise local_exceptions.SpynnakerException( "The simulation has not yet run, therefore spikes cannot" " be retrieved. Please execute the simulation before" " running this command") if conf.config.getboolean("Reports", "outputTimesForSections"): timer = Timer() timer.start_timing() self._spikes = self._vertex.get_spikes( txrx=self._spinnaker.transceiver, placements=self._spinnaker.placements, graph_mapper=self._spinnaker.graph_mapper, compatible_output=compatible_output) if conf.config.getboolean("Reports", "outputTimesForSections"): timer.take_sample() return self._spikes
def get(self, parameter, format, gather): # @ReservedAssignment """ supports getting things from a projection :param parameter: the parameter, "weights, delays, plastic param" :param format: "list" or "array". :param gather: supposedly if True, get connection information from \ all MPI nodes, otherwise only from connections that exist in \ this node. :return: the returns param """ # do the gather check before trying to get data if not gather: common_exceptions.ConfigurationException( "the gather param has no meaning for spinnaker when set to " "false") # try for each possible parameters if parameter in {"weight", "delay", "source", "target"}: return self._get_synaptic_data(format == 'list', parameter) else: # get the n_connections and the parameter and then expand to # correct size size = len(self._get_synaptic_data(format == 'list', 'source')) data = numpy.empty(size) data.fill( self._synapse_information.synapse_dynamics.get_value( parameter)) return data
def _write_key_data(self, spec, routing_info, graph): """ Write the keys of its 8 neighbours """ spec.switch_write_focus(region=self.DATA_REGIONS.NEIGHBOUR_KEYS.value) incoming_edges = graph.get_edges_ending_at_vertex_with_partition_name(self, self.PARTITION_ID) # verify the number of edges if len(incoming_edges) != 8: print(incoming_edges) raise exceptions.ConfigurationException("Should only have 8 edges") # get incoming edges for direction in self._loccation_vertices: key = routing_info.get_routing_info_from_pre_vertex( self._loccation_vertices[direction], self.PARTITION_ID).keys_and_masks[0].key if key is not None: spec.write_value(data=key) else: logger.warning("This lattice miss a edge from direction {}".format(direction)) spec.write_value(data_type=DataType.INT32, data=-1) mask = routing_info.get_routing_info_from_pre_vertex(self._loccation_vertices["S"], self.PARTITION_ID).keys_and_masks[0].mask spec.write_value(data=mask, data_type=DataType.UINT32)
def connect(pre, post, weight=0.0, delay=None, receptor_type=None, p=1, rng=None): raise exceptions.ConfigurationException( "You cannot call connect until you have called setup.")
def _calculate_fpga_cost( self, machine, version, spalloc_server, remote_spinnaker_url, total_runtime, output, runtime_total_milliseconds): """ fpga cost calculation :param machine: machine rep :param version: machine version :param spalloc_server: spalloc server ip :param remote_spinnaker_url: remote spinnaker :param total_runtime: runtime: :param output: the file writer: :param runtime_total_milliseconds: :return: power usage of fpgas """ # if not spalloc, then could be any type of board if spalloc_server is None and remote_spinnaker_url is None: # if a spinn2 or spinn3 (4 chip boards) then they have no fpgas if int(version) == 2 or int(version) == 3: output.write( "A Spinn {} board does not contain any FPGA's, and so " "its energy cost is 0 \n".format(version)) return 0, 0 # if the spinn4 or spinn5 board, need to verify if wrap arounds # are there, if not then assume fppga's are turned off. elif int(version) == 4 or int(version) == 5: # how many fpgas are active n_operational_fpgas = self._board_n_operational_fpgas( machine, machine.ethernet_connected_chips[0]) # active fpgas if n_operational_fpgas > 0: return self._print_out_fpga_cost( total_runtime, n_operational_fpgas, output, version, runtime_total_milliseconds) else: # no active fpgas output.write( "The FPGA's on the Spinn {} board are turned off and " "therefore the energy used by the FPGA is 0\n".format( version)) return 0, 0 else: # no idea where we are raise exceptions.ConfigurationException( "Do not know what the FPGA setup is for this version of " "SpiNNaker machine.") else: # spalloc machine, need to check each board total_fpgas = 0 for ethernet_connected_chip in machine.ethernet_connected_chips: total_fpgas += self._board_n_operational_fpgas( machine, ethernet_connected_chip) return self._print_out_fpga_cost( total_runtime, total_fpgas, output, version, runtime_total_milliseconds)
def add_binary(self, binary): """ Add a binary to the list of things to execute :param binary: The binary to add """ if binary not in self._targets: self._targets[binary] = CoreSubsets() else: raise exceptions.ConfigurationException( "Binary {} already added".format(binary))
def __init__( self, p_connect, allow_self_connections=True, safe=True, verbose=False): AbstractConnector.__init__(self, safe, verbose) self._p_connect = p_connect self._allow_self_connections = allow_self_connections if not 0 <= self._p_connect <= 1: raise exceptions.ConfigurationException( "The probability must be between 0 and 1 (inclusive)")
def get_max_delay(): """ The maximum allowed synaptic delay. :return: """ global _spinnaker if _spinnaker is None: raise front_end_common_exceptions.ConfigurationException( "You currently have not ran setup, please do so before calling " "get_max_delay") else: return _spinnaker.max_supported_delay
def get_time_step(): """ The timestep requested :return: """ global _spinnaker if _spinnaker is None: raise front_end_common_exceptions.ConfigurationException( "You currently have not ran setup, please do so before calling " "get_time_step") else: return _spinnaker.machine_time_step
def __init__(self, size, cellclass, cellparams, spinnaker, label, structure=None): """ Instantiates a :py:object:`Population`. """ if size is not None and size <= 0: raise exceptions.ConfigurationException( "A population cannot have a negative or zero size.") # Create a partitionable_graph vertex for the population and add it # to PACMAN cell_label = label if label is None: cell_label = "Population {}"\ .format(Population._non_labelled_vertex_count) Population._non_labelled_vertex_count += 1 cellparams['label'] = cell_label cellparams['n_neurons'] = size cellparams['machine_time_step'] = spinnaker.machine_time_step cellparams['timescale_factor'] = spinnaker.timescale_factor cellparams['spikes_per_second'] = spinnaker.spikes_per_second cellparams['ring_buffer_sigma'] = spinnaker.ring_buffer_sigma self._vertex = cellclass(**cellparams) self._spinnaker = spinnaker self._delay_vertex = None # Internal structure now supported 23 November 2014 ADR # structure should be a valid Space.py structure type. # generation of positions is deferred until needed. if structure: self._structure = structure self._positions = None else: self._structure = None self._spinnaker._add_population(self) self._spinnaker.add_vertex(self._vertex) self._parameters = PyNNParametersSurrogate(self._vertex) # initialize common stuff self._size = size self._record_spike_file = None self._record_v_file = None self._record_gsyn_file = None self._spikes = None self._v = None self._gsyn = None
def set_constraint(self, constraint): """ Apply a constraint to a population that restricts the processor onto which its sub-populations will be placed. """ if isinstance(constraint, AbstractConstraint): self._vertex.add_constraint(constraint) else: raise exceptions.ConfigurationException( "the constraint entered is not a recongised constraint. " "try again")
def __init__(self, size, cellclass, cellparams, spinnaker, label, structure=None): if size is not None and size <= 0: raise exceptions.ConfigurationException( "A population cannot have a negative or zero size.") # Create a partitionable_graph vertex for the population and add it # to PACMAN cell_label = label if label is None: cell_label = "Population {}".format( spinnaker.none_labelled_vertex_count) spinnaker.increment_none_labelled_vertex_count() # copy the parameters so that the end users are not exposed to the # additions placed by spinnaker. internal_cellparams = dict(cellparams) # set spinnaker targeted parameters internal_cellparams['label'] = cell_label internal_cellparams['n_neurons'] = size internal_cellparams['machine_time_step'] = spinnaker.machine_time_step internal_cellparams['timescale_factor'] = spinnaker.timescale_factor # create population vertex. self._vertex = cellclass(**internal_cellparams) self._spinnaker = spinnaker self._delay_vertex = None # Internal structure now supported 23 November 2014 ADR # structure should be a valid Space.py structure type. # generation of positions is deferred until needed. if structure: self._structure = structure self._positions = None else: self._structure = None self._spinnaker._add_population(self) self._spinnaker.add_partitionable_vertex(self._vertex) # initialise common stuff self._size = size self._record_spike_file = None self._record_v_file = None self._record_gsyn_file = None # parameter self._change_requires_mapping = True
def get_current_time(): """ returns the machine time step defined in setup :return: """ global _spinnaker if _spinnaker is None: raise front_end_common_exceptions.ConfigurationException( "You currently have not ran setup, please do so before calling " "get_current_time") else: return _spinnaker.get_current_time()