Skip to content

Commit 3c799bc

Browse files
committed
Merge remote-tracking branch 'origin/numpy_cap' into numpy_cap
2 parents 54304e4 + 85ca4e9 commit 3c799bc

4 files changed

Lines changed: 145 additions & 53 deletions

File tree

spynnaker/pyNN/models/neuron/population_machine_vertex.py

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
# limitations under the License.
1414
import ctypes
1515
from enum import IntEnum
16-
import os
1716
from typing import List, Optional, Sequence
1817

1918
from numpy import floating
@@ -198,7 +197,7 @@ def __init__(
198197
self.COMMON_REGIONS,
199198
NeuronProvenance.N_ITEMS + SynapseProvenance.N_ITEMS +
200199
SpikeProcessingProvenance.N_ITEMS + MainProvenance.N_ITEMS,
201-
self._PROFILE_TAG_LABELS, self.__get_binary_file_name(app_vertex))
200+
self._PROFILE_TAG_LABELS, app_vertex.combined_binary_file_name)
202201
self.__key: Optional[int] = None
203202
self.__slice_index = slice_index
204203
self.__ring_buffer_shifts = ring_buffer_shifts
@@ -259,22 +258,6 @@ def _synaptic_matrices(self) -> SynapticMatrices:
259258
def _max_atoms_per_core(self) -> int:
260259
return self.__max_atoms_per_core
261260

262-
@staticmethod
263-
def __get_binary_file_name(app_vertex: PopulationVertex) -> str:
264-
"""
265-
Get the local binary filename for this vertex. Static because at
266-
the time this is needed, the local `app_vertex` is not set.
267-
268-
:param PopulationVertex app_vertex:
269-
The associated application vertex
270-
:rtype: str
271-
"""
272-
# Split binary name into title and extension
273-
name, ext = os.path.splitext(app_vertex.neuron_impl.binary_name)
274-
275-
# Reunite title and extension and return
276-
return name + app_vertex.synapse_executable_suffix + ext
277-
278261
@overrides(PopulationMachineCommon.parse_extra_provenance_items)
279262
def parse_extra_provenance_items(
280263
self, label: str, x: int, y: int, p: int,

spynnaker/pyNN/models/neuron/population_neurons_machine_vertex.py

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
from enum import IntEnum
15-
import os
1615
import ctypes
1716
from typing import List, Optional, Sequence
1817

@@ -147,7 +146,7 @@ def __init__(
147146
super().__init__(
148147
label, app_vertex, vertex_slice, sdram, self.COMMON_REGIONS,
149148
NeuronProvenance.N_ITEMS + NeuronMainProvenance.N_ITEMS,
150-
self._PROFILE_TAG_LABELS, self.__get_binary_file_name(app_vertex))
149+
self._PROFILE_TAG_LABELS, app_vertex.neuron_core_binary_file_name)
151150
self.__key: Optional[int] = None
152151
self.__sdram_partition: Optional[
153152
SourceSegmentedSDRAMMachinePartition] = None
@@ -210,22 +209,6 @@ def set_sdram_partition(
210209
"Trying to set SDRAM partition more than once")
211210
self.__sdram_partition = sdram_partition
212211

213-
@staticmethod
214-
def __get_binary_file_name(app_vertex: PopulationVertex) -> str:
215-
"""
216-
Get the local binary filename for this vertex. Static because at
217-
the time this is needed, the local app_vertex is not set.
218-
219-
:param PopulationVertex app_vertex:
220-
The associated application vertex
221-
:rtype: str
222-
"""
223-
# Split binary name into title and extension
224-
name, ext = os.path.splitext(app_vertex.neuron_impl.binary_name)
225-
226-
# Reunite title and extension and return
227-
return name + "_neuron" + ext
228-
229212
@overrides(PopulationMachineCommon.parse_extra_provenance_items)
230213
def parse_extra_provenance_items(
231214
self, label: str, x: int, y: int, p: int,

spynnaker/pyNN/models/neuron/population_synapses_machine_vertex_common.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def __init__(
171171
super().__init__(
172172
label, app_vertex, vertex_slice, sdram, self.COMMON_REGIONS,
173173
SynapseProvenance.N_ITEMS + SpikeProcessingFastProvenance.N_ITEMS,
174-
self._PROFILE_TAG_LABELS, self.__get_binary_file_name(app_vertex))
174+
self._PROFILE_TAG_LABELS, app_vertex.synapse_core_binary_file_name)
175175
self.__sdram_partition: Optional[
176176
SourceSegmentedSDRAMMachinePartition] = None
177177
self.__neuron_vertex: Optional[PopulationNeuronsMachineVertex] = None
@@ -199,19 +199,6 @@ def set_neuron_vertex_and_partition_id(
199199
self.__neuron_vertex = neuron_vertex
200200
self.__partition_id = partition_id
201201

202-
@staticmethod
203-
def __get_binary_file_name(app_vertex: PopulationVertex) -> str:
204-
"""
205-
Get the local binary filename for this vertex. Static because at
206-
the time this is needed, the local `app_vertex` is not set.
207-
208-
:param PopulationVertex app_vertex:
209-
The associated application vertex
210-
:rtype: str
211-
"""
212-
# Reunite title and extension and return
213-
return "synapses" + app_vertex.synapse_executable_suffix + ".aplx"
214-
215202
@overrides(PopulationMachineCommon.get_recorded_region_ids)
216203
def get_recorded_region_ids(self) -> Sequence[int]:
217204
ids = self._pop_vertex.synapse_recorder.recorded_ids_by_slice(

spynnaker/pyNN/models/neuron/population_vertex.py

Lines changed: 142 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from collections import defaultdict
1616
import logging
1717
import math
18+
import os
1819
from typing import (
1920
Any, Collection, Dict, Iterable, List, Optional, Sequence, Tuple, Union,
2021
cast, TYPE_CHECKING)
@@ -486,6 +487,73 @@ def set_max_atoms_per_dimension_per_core(
486487
def set_structure(self, structure: BaseStructure) -> None:
487488
self.__structure = structure
488489

490+
@property
491+
def combined_binary_file_name(self) -> str:
492+
"""
493+
The name of the combined binary file for the vertex.
494+
"""
495+
# Split binary name into title and extension
496+
name, ext = os.path.splitext(self.__neuron_impl.binary_name)
497+
498+
# Reunite title and extension and return
499+
return name + self.synapse_executable_suffix + ext
500+
501+
@property
502+
def neuron_core_binary_file_name(self) -> str:
503+
"""
504+
The name of the neuron core binary file for the vertex.
505+
"""
506+
# Split binary name into title and extension
507+
name, ext = os.path.splitext(self.__neuron_impl.binary_name)
508+
509+
# Reunite title and extension and return
510+
return name + "_neuron" + ext
511+
512+
@property
513+
def synapse_core_binary_file_name(self) -> str:
514+
"""
515+
The name of the synapse core binary file for the vertex.
516+
"""
517+
return "synapses" + self.synapse_executable_suffix + ".aplx"
518+
519+
@property
520+
def combined_binary_exists(self) -> bool:
521+
"""
522+
Whether the combined binary file exists.
523+
524+
:rtype: bool
525+
"""
526+
# If we are in virtual machine mode, we can work without binaries
527+
# so easier to assume they exist
528+
if get_config_bool("Machine", "virtual_board"):
529+
return True
530+
try:
531+
SpynnakerDataView().get_executable_path(
532+
self.combined_binary_file_name)
533+
return True
534+
except KeyError:
535+
return False
536+
537+
@property
538+
def split_binaries_exist(self) -> bool:
539+
"""
540+
Whether the split binary files exist.
541+
542+
:rtype: bool
543+
"""
544+
# If we are in virtual machine mode, we can work without binaries
545+
# so easier to assume they exist
546+
if get_config_bool("Machine", "virtual_board"):
547+
return True
548+
try:
549+
SpynnakerDataView().get_executable_path(
550+
self.neuron_core_binary_file_name)
551+
SpynnakerDataView().get_executable_path(
552+
self.synapse_core_binary_file_name)
553+
return True
554+
except KeyError:
555+
return False
556+
489557
@property
490558
def use_combined_core(self) -> bool:
491559
"""
@@ -495,6 +563,15 @@ def use_combined_core(self) -> bool:
495563
496564
:rtype: bool
497565
"""
566+
# If there are no binaries at all, complain!
567+
if not self.combined_binary_exists and not self.split_binaries_exist:
568+
raise SynapticConfigurationException(
569+
"This model has no binaries! Please compile the binaries"
570+
f" {self.combined_binary_file_name} and/or"
571+
f" ({self.synapse_core_binary_file_name} and"
572+
f" {self.neuron_core_binary_file_name})"
573+
" before running the simulation.")
574+
498575
# If we can't use a combined core, use a split core
499576
if not self.__synapse_dynamics.is_combined_core_capable:
500577
if not self.__synapse_dynamics.is_split_core_capable:
@@ -508,6 +585,13 @@ def use_combined_core(self) -> bool:
508585
f"The synapse dynamics {self.__synapse_dynamics} must be"
509586
" run using a synapse core separate from a neuron core."
510587
" Please set the number of synapse cores to 1 or greater.")
588+
if not self.split_binaries_exist:
589+
raise SynapticConfigurationException(
590+
"This model requires split binaries"
591+
f" {self.neuron_core_binary_file_name} and"
592+
f" {self.synapse_core_binary_file_name} but they do not "
593+
"exist. Please compile the split binaries before "
594+
"running the simulation.")
511595
return False
512596

513597
# If we can't use a split core, use a combined core
@@ -518,21 +602,67 @@ def use_combined_core(self) -> bool:
518602
f"The synapse dynamics {self.__synapse_dynamics} must be"
519603
" run using a combined synapse-neuron core."
520604
" Please set the number of synapse cores to 0.")
605+
if not self.combined_binary_exists:
606+
raise SynapticConfigurationException(
607+
"This model requires a combined binary"
608+
f" {self.combined_binary_file_name}, but it does not "
609+
"exist. Please compile the combined binary before "
610+
"running the simulation.")
521611
return True
522612

523613
# If the user has chosen to have a synapse core, add one
524614
if self.__n_synapse_cores is not None and self.__n_synapse_cores > 0:
615+
if not self.split_binaries_exist:
616+
raise SynapticConfigurationException(
617+
"This model is configured to use split binaries"
618+
f" {self.neuron_core_binary_file_name} and"
619+
f" {self.synapse_core_binary_file_name} but they do not "
620+
"exist. Please compile the split binaries before "
621+
"running the simulation.")
525622
return False
526623

624+
# If the user has chosen to have no synapse cores, use a combined core
625+
if self.__n_synapse_cores is not None and self.__n_synapse_cores == 0:
626+
if not self.combined_binary_exists:
627+
raise SynapticConfigurationException(
628+
"This model is configured to use a combined binary"
629+
f" {self.combined_binary_file_name}, but it does not "
630+
"exist. Please compile the combined binary before "
631+
"running the simulation.")
632+
return True
633+
527634
# If the time-step is less than 1, use combined core if no synapse
528635
# cores are needed, otherwise use split core
529636
# TODO: Look at if it is possible to include neurons in a combined
530637
# core calculation and update to allow a choice of combined core if
531638
# neurons and synapses fit on a single core
532639
if SpynnakerDataView().get_simulation_time_step_ms() < 1.0:
533-
return self.n_synapse_cores_required == 0
640+
use_combined = (self.n_synapse_cores_required == 0)
641+
642+
# We want combined, but it doesn't exist, so use split
643+
# (which is fine)
644+
if use_combined and not self.combined_binary_exists:
645+
return False
534646

535-
# If the timestep is 1 or greater, use a combined core generally
647+
# We want split, but it doesn't exist, so use combined, which needs
648+
# a warning as it might not work at this time-step!
649+
if not use_combined and not self.split_binaries_exist:
650+
logger.warning(
651+
"The synapse dynamics are set to use a split core, but "
652+
"the split binaries do not exist. Using the combined "
653+
"core instead, but this may not work at this time-step. "
654+
"To avoid this warning please build the split binaries "
655+
f"{self.neuron_core_binary_file_name} and "
656+
f"{self.synapse_core_binary_file_name}.")
657+
return True
658+
659+
# Use the recommended mode
660+
return use_combined
661+
662+
# If the timestep is 1 or greater, use a combined core generally,
663+
# unless only a split core exists!
664+
if not self.combined_binary_exists:
665+
return False
536666
return True
537667

538668
@property
@@ -616,7 +746,16 @@ def __update_n_synapse_cores(self) -> int:
616746

617747
# If the number of cores needed is more than the maximum, use the
618748
# maximum
619-
self.__n_synapse_cores = min(max_n_cores, n_synapse_cores)
749+
if n_synapse_cores > max_n_cores:
750+
logger.warning(
751+
f"Ideally this execution would need {n_synapse_cores} synapse "
752+
f"cores, but only {max_n_cores} cores are available. This may "
753+
"mean that the simulation does not work correctly. Potential "
754+
"solutions include increasing the time_scale_factor, or "
755+
"reducing the number of synapses incoming into each "
756+
"population")
757+
n_synapse_cores = max_n_cores
758+
self.__n_synapse_cores = n_synapse_cores
620759
assert self.__n_synapse_cores is not None
621760
return self.__n_synapse_cores
622761

0 commit comments

Comments
 (0)