project-rig / nengo_spinnaker Goto Github PK
View Code? Open in Web Editor NEWSpiNNaker based Nengo simulator.
License: MIT License
SpiNNaker based Nengo simulator.
License: MIT License
Have tried running the following script using nengo_gui and get the exception at the bottom of the page. It works using nengo, but fails with nengo_spinnaker, causing arbitrary cores to go into RTE.
from nengo.utils.functions import piecewise
import nengo
import numpy as np
model = nengo.Network("Piecewise bug")
with model:
# Piecewise controller
some_control = nengo.Node(output=piecewise({0: 1, 2: 0}))
# Some input into A
some_input = nengo.Node(output=lambda t: [np.pi / 2, np.pi / 4])
# Intermediary node
enabled = nengo.Node(size_in=1)
# Some ensemble
A = nengo.Ensemble(100, 2, radius=1.6)
# Control signal feeds into intermediary node
nengo.Connection(some_control, enabled)
# Intermediary node inhibits population A
nengo.Connection(enabled, A.neurons, transform=[[-2.5]] * A.n_neurons)
# Some input in A just to check that inhibition works
nengo.Connection(some_input, A)
Exception in thread Thread-8:
Traceback (most recent call last):
File "c:\Python27\lib\threading.py", line 810, in __bootstrap_inner
self.run()
File "c:\Python27\lib\threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\nengo_gui\nengo_gui\page.py", line 443, in runner
self.sim.run_steps(self.sim.max_steps)
File "C:\nengo_spinnaker\nengo_spinnaker\simulator.py", line 179, in run_steps
self._run_steps(n_steps)
File "C:\nengo_spinnaker\nengo_spinnaker\simulator.py", line 247, in _run_steps
status = self.controller.get_processor_status(p, x, y)
File "c:\Python27\lib\site-packages\rig\utils\contexts.py", line 172, in f_
return f(self, *args, **new_kwargs)
File "c:\Python27\lib\site-packages\rig\machine_control\machine_controller.py", line 531, in get_processor_status
state["rt_code"] = consts.RuntimeException(state["rt_code"])
File "c:\Python27\lib\site-packages\enum\__init__.py", line 330, in __call__
return cls.__new__(cls, value)
File "c:\Python27\lib\site-packages\enum\__init__.py", line 642, in __new__
raise ValueError("%s is not a valid %s" % (value, cls.__name__))
ValueError: 185 is not a valid RuntimeException
The value of the error seems random, it's rarely the same.
This is something that I normally think is a Bad Thing ™️ but would be useful for @celiasmith and @studywolf among others. @neworderofjamie, would you have any problem moving to us storing binaries in the repository and ensuring that we keep them up-to-date with the branches they are related to?
Ran into a problem with the most recent version of Nengo about paramter naming, it was resolved by using the following code in config.py
(adding name=
):
def add_spinnaker_params(config):
"""Add SpiNNaker specific parameters to a configuration object."""
# Add simulator parameters
config.configures(Simulator)
config[Simulator].set_param("placer", CallableParameter(name="placer", default=par.place))
config[Simulator].set_param("placer_kwargs", DictParam(name="placer_kwargs", default={}))
config[Simulator].set_param("allocater",
CallableParameter(name="allocater", default=par.allocate))
config[Simulator].set_param("allocater_kwargs",
DictParam(name="allocater_kwargs", default={}))
config[Simulator].set_param("router", CallableParameter(name="router", default=par.route))
config[Simulator].set_param("router_kwargs", DictParam(name="router_kwargs", default={}))
config[Simulator].set_param("node_io", Parameter(name="node_io", default=Ethernet))
config[Simulator].set_param("node_io_kwargs", DictParam(name="node_io_kwargs", default={}))
# Add function_of_time parameters to Nodes
config[nengo.Node].set_param("function_of_time", BoolParam(name="function_of_time", default=False))
config[nengo.Node].set_param("function_of_time_period",
NumberParam(name="function_of_time_kwargs", default=None, optional=True))
# Add profiling parameters to Ensembles
config[nengo.Ensemble].set_param("profile", BoolParam(name="profile", default=False))
config[nengo.Ensemble].set_param("profile_num_samples",
NumberParam(name="profile_num_samples", default=None, optional=True))
nengo/nengo#1053 has changed the cache API.
Should be a trivial fix.
with nengo.Network() as model:
a = nengo.Ensemble(100, 1)
ptn = nengo.Node(size_in=1)
nengo.Connection(a, ptn)
Causes a KeyError in nengo_spinnaker/operators/filter.py::make_vertices
line 51.
Here's a minimal(ish) example that exhibits some strange behaviour:
import nengo
import numpy as np
from nengo import spa
import ctn_benchmark
class Vision(ctn_benchmark.Benchmark):
def params(self):
self.default('number of neurons', n_neurons=80)
self.default('dim input', dim_input=1260)
self.default('dim output', dim_output=32)
self.default('fixed input', fixed_input=False)
self.default('function of time', function_of_time=False)
self.default('aligned vector', aligned_vector=False)
def model(self, p):
model = nengo.Network()
with model:
a = nengo.Ensemble(p.n_neurons, p.dim_input)
b = nengo.Node(None, size_in=p.dim_output)
vocab = spa.Vocabulary(p.dim_output)
if p.aligned_vector:
vocab.add('A', np.eye(p.dim_output)[0])
nengo.Connection(a, b, synapse=0.005,
function=lambda x: vocab.parse('A').v)
if p.fixed_input:
stim = nengo.Node(np.eye(p.dim_input)[0])
else:
def stim_func(t):
return np.eye(p.dim_input)[0]
stim = nengo.Node(stim_func)
if p.function_of_time and p.backend == 'nengo_spinnaker':
import nengo_spinnaker
nengo_spinnaker.add_spinnaker_params(model.config)
model.config[stim].function_of_time = True
nengo.Connection(stim, a)
self.p = nengo.Probe(b, synapse=0.03)
self.vocab = vocab
return model
def evaluate(self, p, sim, plot):
sim.run(0.5)
if plot is not None:
plot.plot(sim.trange(), np.dot(sim.data[self.p],
self.vocab.vectors.T))
return {}
if __name__ == '__main__':
Vision().run()
This model is a simple large-vector input being fed into one ensemble, from which we decode out a smaller-dimensional function which we send to a passthrough Node and probe it.
Using branch dev0716, if we run this with 100 neurons, we run into this slicing problem:
INFO:nengo_spinnaker.simulator:Building netlist
Traceback (most recent call last):
File "vision3.py", line 57, in <module>
Vision().run()
File "c:\users\terry\documents\github\ctn_benchmarks\ctn_benchmark\benchmark.py", line 122, in run
sim = Simulator(model, dt=p.dt)
File "c:\users\terry\documents\github\nengo_spinnaker\nengo_spinnaker\simulator.py", line 139, in __init__
self.netlist = self.model.make_netlist(self.max_steps or 0)
File "c:\users\terry\documents\github\nengo_spinnaker\nengo_spinnaker\builder\builder.py", line 340, in make_netlist
self, *args, **kwargs
File "c:\users\terry\documents\github\nengo_spinnaker\nengo_spinnaker\operators\lif.py", line 453, in make_vertices
cluster_vertices = cluster.make_vertices(cycles)
File "c:\users\terry\documents\github\nengo_spinnaker\nengo_spinnaker\operators\lif.py", line 619, in make_vertices
assert n_slices <= 16 # Too many cores in the cluster
AssertionError
To fix this, we adjust lif.py
to adjust the memory padding:
dtcm_constraint = partition.Constraint(16 * 64 * 2**10,
0.9) # 90% of 16 cores DTCM
# The number of cycles available is 200MHz * the machine timestep; or
#200 * the machine timestep in microseconds.
cycles = 200 * model.machine_timestep
cpu_constraint = partition.Constraint(cycles * 16,
0.8) # 80% of 16 cores compute
For the examples run on this page, I've set the 0.9 and 0.8 values to 0.5 and 0.5.
Running this model with different parameters produces a variety of results.
If I run the model as it is (n_neurons=80, fixed_input=False, function_of_time=False, aligned_vector=False) then the system is passing in the input during runtime and I get a whole bunch of watchdog errors:
Core (2, 9, 2) in state AppState.watchdog
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:584 Malloc ensemble.input (5040 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:286 Malloc filters->filters (20 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:308 Malloc filters->filters[f].input (8 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:310 Malloc filters->filters[f].input->value (360 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:318 Malloc filters->filters[f].output (360 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:81 Malloc filter->state (8 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:240 Malloc filters->routes (16 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:655 Malloc ensemble.encoders (30240 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:661 Malloc ensemble.bias (24 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:666 Malloc ensemble.gain (24 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:671 Malloc ensemble.population_lengths (56 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:697 Malloc ensemble.spikes (56 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:703 Malloc ensemble.decoders (640 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:716 Malloc ensemble.keys (8 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/neuron_lif.c:17 Malloc ensemble->state (16 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/neuron_lif.c:21 Malloc state->voltages (24 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/neuron_lif.c:25 Malloc state->refractory (24 bytes)
PES learning: Num rules:0
Voja learning: Num rules:0, One over radius:1.000000
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/recording.c:14 Malloc buffer->buffer (12 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/recording.c:14 Malloc buffer->buffer (4 bytes)
If I give it a fixed input (n_neurons=80, fixed_input=True, function_of_time=False, aligned_vector=False), then the value gets precomputed, rolled into the bias, and it works great:
But, if I now increase the number of neurons to 100 (n_neurons=100, fixed_input=True, function_of_time=False, aligned_vector=False), it runs but gives an incorrect result (much much smaller than it should be):
Bizarrely, if I set aligned_vector to True, it now works fine at both 80 and 100 neurons. This is bizarre, since the only change is that the desired output is [1,0,0,0,0,0,...] instead of a randomly chosen 32-dimensional unit vector.
(n_neurons=100, fixed_input=True, function_of_time=False, aligned_vector=False)
(n_neurons=80, fixed_input=True, function_of_time=False, aligned_vector=False)
Now let's see what happens if we set the input to be a function_of_time Node.
The function_of_time approach works great with 100 neurons and aligned vectors:
(n_neurons=100, fixed_input=False, function_of_time=True, aligned_vector=True)
If we don't go with an aligned_vector, we get the same problem as above:
(n_neurons=100, fixed_input=False, function_of_time=True, aligned_vector=False)
But now if I go down to 80 neurons, it dies with a watchdog error:
(n_neurons=80, fixed_input=False, function_of_time=True, aligned_vector=False)
INFO:nengo_spinnaker.simulator:Running simulation...
Core (7, 8, 1) in state AppState.watchdog
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:584 Malloc ensemble.input (5040 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:286 Malloc filters->filters (20 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:308 Malloc filters->filters[f].input (8 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:310 Malloc filters->filters[f].input->value (360 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:318 Malloc filters->filters[f].output (360 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:81 Malloc filter->state (8 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/common/input_filtering.c:240 Malloc filters->routes (16 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:655 Malloc ensemble.encoders (30240 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:661 Malloc ensemble.bias (24 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:666 Malloc ensemble.gain (24 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:671 Malloc ensemble.population_lengths (56 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:697 Malloc ensemble.spikes (56 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:703 Malloc ensemble.decoders (960 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/ensemble.c:716 Malloc ensemble.keys (12 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/neuron_lif.c:17 Malloc ensemble->state (16 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/neuron_lif.c:21 Malloc state->voltages (24 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/neuron_lif.c:25 Malloc state->refractory (24 bytes)
PES learning: Num rules:0
Voja learning: Num rules:0, One over radius:1.000000
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/recording.c:14 Malloc buffer->buffer (12 bytes)
/local/mundya/nengo_devel/nengo_spinnaker/spinnaker_components/ensemble/recording.c:14 Malloc buffer->buffer (4 bytes)
At the moment an interposer is inserted if it would reduce network load, to reduce the number of processors required for a given model this should be changed to insert an interposer only if it would improve network load and the network load was originally above some threshold.
I've written this small script to play around with transforms. The idea is that the output point is supposed to be rotated by 180° around the origin. When running with Nengo backend the both the input and output follow the outline of the unit circle (as expected). When running on Nengo SpiNNaker both the input and output follow a very flattened ellipse either oriented on the X or Y axis.
This has been tested using nengo_gui.
import nengo
import numpy as np
model = nengo.Network("Rotation")
with model:
tau = 0.1
x_in = nengo.Node(output=np.sin)
y_in = nengo.Node(output=np.cos)
rotation = nengo.Ensemble(n_neurons=300, dimensions=2, radius=1.2)
output = nengo.Ensemble(n_neurons=300, dimensions=2, radius=1.2)
nengo.Connection(x_in, rotation[0])
nengo.Connection(y_in, rotation[1])
nengo.Connection(rotation, output, transform=[[-1, 0], [0, -1]])
This appears to be related to pass nodes and the transform that should be assumed for connections from objects into neurons.
Needs further investigation and a MWE.
with nengo.Network() as model:
# Ensemble with constant value
val = nengo.Node(0.5)
ens = nengo.Ensemble(100, 1)
nengo.Connection(val, ens)
# Node -> Passthrough Node -> Neurons
control = nengo.Node(lambda t: 0.0 if t < 0.5 else 1.0)
ptn = nengo.Node(size_in=1)
nengo.Connection(control, ptn)
nengo.Connection(ptn, ens.neurons, transform=[[-10.0]] * ens.n_neurons)
# Probe
p = nengo.Probe(ens, synapse=0.005)
should produce something like:
For more fun
with nengo.Network() as model:
# Ensemble with constant value
val = nengo.Node(0.5)
ens = nengo.Ensemble(100, 1)
nengo.Connection(val, ens)
# Node -> Passthrough Node -> Neurons
control = nengo.Node(lambda t: 0.0 if t < 0.5 else 1.0)
ptn = nengo.Node(size_in=ens.n_neurons)
nengo.Connection(control, ptn, transform=[[-10.0]] * ens.n_neurons)
nengo.Connection(ptn, ens.neurons)
should be equivalent.
This is the MWE for #27.
Windows: %userprofile%\nengo\nengo_spinnaker.conf
This should be %userprofile%`.`nengo\nengo_spinnaker.conf
Should be modified in the config file as well. Don't know if the same problem applies to other platforms, though I suspect it does.
This or the magic config location finding incantation like spalloc would be super-useful
import numpy as np
import nengo
import nengo_spinnaker
model = nengo.Network(seed=1)
with model:
node_in = nengo.Node(output=[2,3,1,5])
ens_out = nengo.Ensemble(n_neurons=200, dimensions=6)
conn = nengo.Connection(node_in[[1,3]], ens_out[2:], function=lambda x: [x[0], x[1], x[0], x[1]])
print nengo.utils.builder.full_transform(conn)
s = nengo_spinnaker.Simulator(model)
s.run(5)
s.close()
throws
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 808, in __bootstrap_inner
self.run()
File "/home/tdewolf/Dropbox/code/nengo_spinnaker/nengo_spinnaker/node_io/ethernet.py", line 177, in run
packet.src_cpu)]
KeyError: (3, 2, 13)
note from andrew - "this is probably also broken for function of time nodes"
Hi, I wonder where I can get the Spinnaker board? Thanks.
Minimal example:
import nengo
import numpy as np
model = nengo.Network("Broken!")
with model:
some_input = nengo.Node(np.sin)
some_inhibition = nengo.Node(np.cos)
A = nengo.networks.EnsembleArray(n_neurons=100, n_ensembles=1, ens_dimensions=1)
inhibiting_input = A.add_neuron_input()
nengo.Connection(some_input, A.input)
nengo.Connection(some_inhibition, inhibiting_input, transform=[[-2.5]]*100)
This works with nengo, fails with nengo_spinnaker.
Traceback (most recent call last):
File "/home/bogdanp/nengo_gui/nengo_gui/page.py", line 435, in build
self.sim = backend.Simulator(self.model)
File "/home/bogdanp/nengo_spinnaker/nengo_spinnaker/simulator.py", line 103, in __init__
self.model.build(network, **builder_kwargs)
File "/home/bogdanp/nengo_spinnaker/nengo_spinnaker/builder/builder.py", line 204, in build
self._build_network(network)
File "/home/bogdanp/nengo_spinnaker/nengo_spinnaker/builder/builder.py", line 212, in _build_network
self._build_network(subnet)
File "/home/bogdanp/nengo_spinnaker/nengo_spinnaker/builder/builder.py", line 224, in _build_network
self.make_connection(connection)
File "/home/bogdanp/nengo_spinnaker/nengo_spinnaker/builder/builder.py", line 257, in make_connection
sink = self._sink_getters[post_type](self, conn)
File "/home/bogdanp/nengo_spinnaker/nengo_spinnaker/builder/ensemble.py", line 64, in get_neurons_sink
elif np.all(connection.transform[1:] == connection.transform[0]):
ValueError: cannot slice a 0-d array
Here's a simple test case:
import nengo
model = nengo.Network()
with model:
stim1 = nengo.Node([0])
stim2 = nengo.Node([0])
a = nengo.Ensemble(n_neurons=100, dimensions=2)
nengo.Connection(stim1, a[0])
nengo.Connection(stim2, a[1])
One of these Nodes will work fine, but the other seems to be almost ignored by the a
ensemble.
If I do this as a single Node, it all works fine:
import nengo
model = nengo.Network()
with model:
stim = nengo.Node([0,0])
a = nengo.Ensemble(n_neurons=100, dimensions=2)
nengo.Connection(stim, a)
Facing the below issue:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/nengo_gui-0.4.5.dev0-py2.7.egg/nengo_gui/page.py", line 488, in build
self.sim = backend.Simulator(self.model)
File "/home/samia/Documents/nengo_spinnaker-master/nengo_spinnaker/simulator.py", line 112, in init
self.model.build(network, **builder_kwargs)
File "/home/samia/Documents/nengo_spinnaker-master/nengo_spinnaker/builder/builder.py", line 211, in build
self.connection_map.insert_and_stack_interposers()
File "/home/samia/Documents/nengo_spinnaker-master/nengo_spinnaker/builder/model.py", line 174, in insert_and_stack_interposers
interposers, cm = self.insert_interposers()
File "/home/samia/Documents/nengo_spinnaker-master/nengo_spinnaker/builder/model.py", line 222, in insert_interposers
trans = tps.full_transform(False, False)
AttributeError: 'object' object has no attribute 'full_transform'
Nengo version being used is 2.8.0
Any help with resolving this issue is much appreciated.
Thanks!
In Nengo we can do
conn = nengo.Connection(a, b, learning_rule_type=nengo.PES())
nengo.Connection(target, conn.learning_rule, transform=-1)
nengo.Connection(b, conn.learning_rule, transform=1)
it would be great to be able to do that in Nengo_Spinnaker as well!
Running any sort of simulation while in a virtualenv seems to throw the error at the bottom of the page.
import nengo
model = nengo.Network()
with model:
stim = nengo.Node([0])
a = nengo.Ensemble(n_neurons=50, dimensions=1)
nengo.Connection(stim, a)
nengo_gui with debug output shows it crashes at building the model
INFO:nengo_spinnaker.utils.machine_control:Checking that SpiNNaker board '192.168.240.1' is booted
INFO:nengo_spinnaker.utils.machine_control:Board is booted with SC&MP/SpiNNaker v1.33
DEBUG:nengo_spinnaker.simulator:Building model
Actual error
Traceback (most recent call last):
File "/home/PhD15/bogdanp/nengo_gui/nengo_gui/page.py", line 423, in build
self.sim = backend.Simulator(self.model)
File "/home/PhD15/bogdanp/AlanProject/venv/lib/python2.7/site-packages/nengo_spinnaker-0.2.4-py2.7.egg/nengo_spinnaker/simulator.py", line 94, in __init__
File "/home/PhD15/bogdanp/AlanProject/venv/lib/python2.7/site-packages/nengo_spinnaker-0.2.4-py2.7.egg/nengo_spinnaker/builder/builder.py", line 212, in build
File "/home/PhD15/bogdanp/AlanProject/venv/lib/python2.7/site-packages/nengo_spinnaker-0.2.4-py2.7.egg/nengo_spinnaker/builder/builder.py", line 232, in _build_network
File "/home/PhD15/bogdanp/AlanProject/venv/lib/python2.7/site-packages/nengo_spinnaker-0.2.4-py2.7.egg/nengo_spinnaker/builder/builder.py", line 252, in make_connection
File "/home/PhD15/bogdanp/AlanProject/venv/lib/python2.7/site-packages/nengo_spinnaker-0.2.4-py2.7.egg/nengo_spinnaker/builder/ensemble.py", line 168, in build_from_ensemble_connection
TypeError: cached_solver() takes at least 6 arguments (3 given)
It should be possible to simulate ~8x 100-neuron 1-dimension ensembles on a single processor (allowing for .5ms for a simulation step). Not only will this significantly reduce the number of cores required to simulate meaningful models (cconv should benefit particularly) but it should reduce the burstiness of the network load and, under my modelling, reduces the size of routing tables.
indent should be removed after line 36, i believe! fix:
# Import modules
import csv
import numpy as np
import nengo
import nengo_spinnaker
# Import classes
from nengo.processes import WhiteNoise
from nengo_spinnaker.utils import profiling
# Parameters to profile
dimensions = 1
ensemble_size = 200
model = nengo.Network()
with model:
# Create standard communication channel network with white noise input
inp = nengo.Node(WhiteNoise(), label="inp")
inp_p = nengo.Probe(inp)
pre = nengo.Ensemble(ensemble_size, dimensions=dimensions, label="pre")
pre_p = nengo.Probe(pre, synapse=0.01)
nengo.Connection(inp, pre)
post = nengo.Ensemble(ensemble_size, dimensions=dimensions, label="post")
posts_p = nengo.Probe(post, synapse = 0.01)
nengo.Connection(pre, post,
function=lambda x: np.random.random(dimensions))
# Setup SpiNNaker-specific options to supply white noise from on
# chip and profile the ensemble at the start of the channel
nengo_spinnaker.add_spinnaker_params(model.config)
model.config[inp].function_of_time = True
model.config[pre].profile = True
# Create a SpiNNaker simulator and run model
sim = nengo_spinnaker.Simulator(model)
with sim:
sim.run(10.0)
# Read profiler data
profiler_data = sim.profiler_data[pre]
# Open CSV file and create writer
with open("profile_communication_channel.csv", "wb") as csv_file:
csv_writer = csv.writer(csv_file)
# Write header row for CSV with extra columns
# for number of neurons and dimensions
profiling.write_csv_header(profiler_data, csv_writer,
["Num neurons", "Dimensions"])
# Write a row from the profiler data dollo
profiling.write_csv_row(profiler_data, csv_writer,
[ensemble_size, dimensions])
I'm getting this error (again on the new_ensembles-new-learning
branch)
Traceback (most recent call last):
File "scrap.py", line 15, in <module>
sim.run(100)
File "/home/pawel/src/nengo_spinnaker/nengo_spinnaker/simulator.py", line 190, in run
self.run_steps(steps)
File "/home/pawel/src/nengo_spinnaker/nengo_spinnaker/simulator.py", line 196, in run_steps
self._run_steps(n_steps)
File "/home/pawel/src/nengo_spinnaker/nengo_spinnaker/simulator.py", line 260, in _run_steps
len(self.netlist.vertices))
File "/home/pawel/src/nengo_spinnaker/nengo_spinnaker/simulator.py", line 292, in _wait_for_transition
raise Exception("Unexpected core failures before reaching %s state." % desired_to_state)
Exception: Unexpected core failures before reaching AppState.sync0 state.
using this code
import nengo
import numpy as np
model = nengo.Network()
with model:
# ens = nengo.Ensemble(n_neurons=2000, dimensions=3) # doesn't fail
ens = nengo.Ensemble(n_neurons=2000, dimensions=4) # fails
import nengo_spinnaker
import logging
logging.basicConfig(level=logging.DEBUG)
nengo_spinnaker.add_spinnaker_params(model.config)
sim = nengo_spinnaker.Simulator(model)
print 'model built.'
sim.run(100)
I haven't actually tried with fewer neurons but it's real late and i'm tired! 💨
Example:
with nengo.Network() as model:
a = nengo.Node(0.0)
b = nengo.Node(size_in=2)
c = nengo.Ensemble(100, 2)
nengo.Connection(a, b, function=lambda x: [np.sin(x), 1])
nengo.Connection(b, c)
Results in:
Traceback (most recent call last):
File "test_1.py", line 15, in <module>
sim.run(1.0)
File "/local/mundya/nengo_devel/nengo_spinnaker/nengo_spinnaker/simulator.py", line 173, in run
self.run_steps(steps)
File "/local/mundya/nengo_devel/nengo_spinnaker/nengo_spinnaker/simulator.py", line 179, in run_steps
self._run_steps(n_steps)
File "/local/mundya/nengo_devel/nengo_spinnaker/nengo_spinnaker/simulator.py", line 199, in _run_steps
self.netlist.before_simulation(self, steps)
File "/local/mundya/nengo_devel/nengo_spinnaker/nengo_spinnaker/netlist.py", line 296, in before_simulation
fn(self, simulator, n_steps)
File "/local/mundya/nengo_devel/nengo_spinnaker/nengo_spinnaker/operators/value_source.py", line 161, in before_simulation
output.append(np.dot(transform, v.T))
AttributeError: 'list' object has no attribute 'T'
Reported by @pabogdan
As well as functions and constant values, nodes can output Processes (nengo.processes.Process derived things). First problem occurs in builder https://github.com/project-rig/nengo_spinnaker/blob/master/nengo_spinnaker/builder/ensemble.py#L35 which can be simply fixed with a not isinstance(connection.pre_obj.output, Process)
test (is that the best way?) but it then falls over in https://github.com/project-rig/nengo_spinnaker/blob/master/nengo_spinnaker/operators/value_source.py#L73 where I'm a little sketchy as to what's going on. The following example reproduces:
import nengo
import nengo_spinnaker
import numpy as np
import matplotlib.pyplot as plt
from nengo.processes import WhiteSignal
model = nengo.Network()
with model:
inp = nengo.Node(WhiteSignal(60, high=5), size_out=2)
pre = nengo.Ensemble(60, dimensions=2)
nengo.Connection(inp, pre)
pre_p = nengo.Probe(pre, synapse=0.01)
nengo_spinnaker.add_spinnaker_params(model.config)
model.config[inp].function_of_time = True
sim = nengo_spinnaker.SpiNNakerSimulator(model)
sim.run(10.0)
The following piece of code is a minimal example of a bug arising when using nengo_gui with SpiNNaker. It works fine both on Nengo and SpiNNaker when you don't have a graph (probe) to follow the value of the "output" node. When adding the probe, Nengo runs, but Nengo_SpiNNaker doesn't, giving the stack trace at the bottom.
import nengo
import numpy as np
model = nengo.Network("Buggy - output not working")
with model:
input = nengo.Node(lambda t: np.sin(t))
middle = nengo.Ensemble(50, 1)
output = nengo.Node(size_in=1)
nengo.Connection(input, middle)
nengo.Connection(middle, output)
Exception in thread Thread-126:
Traceback (most recent call last):
File "c:\Python27\lib\threading.py", line 810, in __bootstrap_inner
self.run()
File "c:\Python27\lib\threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\nengo_gui\nengo_gui\viz.py", line 129, in runner
self.build()
File "C:\nengo_gui\nengo_gui\viz.py", line 98, in build
self.sim = backend.Simulator(self.model)
File "C:\nengo_spinnaker\nengo_spinnaker\simulator.py", line 111, in __init__
self.netlist = self.model.make_netlist(self.max_steps or 0)
File "C:\nengo_spinnaker\nengo_spinnaker\builder\builder.py", line 328, in make_netlist
self, *args, **kwargs
File "C:\nengo_spinnaker\nengo_spinnaker\operators\filter.py", line 83, in make_vertices
SDRAM: regions.utils.sizeof_regions(self.regions, slice(None)),
File "C:\nengo_spinnaker\nengo_spinnaker\regions\utils.py", line 43, in sizeof_regions
size = sum(r.sizeof_padded(vertex_slice) for r in regions if r is not None)
File "C:\nengo_spinnaker\nengo_spinnaker\regions\utils.py", line 43, in
size = sum(r.sizeof_padded(vertex_slice) for r in regions if r is not None)
File "C:\nengo_spinnaker\nengo_spinnaker\regions\region.py", line 12, in sizeof_padded
n_bytes = self.sizeof(vertex_slice)
File "C:\nengo_spinnaker\nengo_spinnaker\regions\matrix.py", line 83, in sizeof
self.matrix[self.expanded_slice(vertex_slice)].nbytes)
IndexError: too many indices for array
Nengo SpiNNaker seems to just hang when trying this. Minimal example:
import nengo
import numpy as np
model = nengo.Network("Network of networks")
with model:
net1 = nengo.Network("Subnet")
with net1:
input_value = nengo.Node(size_in=1)
A = nengo.Ensemble(40, 1)
output_val = nengo.Node(size_in=1)
nengo.Connection(input_value, A)
nengo.Connection(A, output_val)
sine = nengo.Node(output=np.sin)
nengo.Connection(sine, input_value)
This works fine using Nengo, outputing as expected.
INFO:nengo_spinnaker.utils.machine_control:Checking that SpiNNaker board '172.16.1.2' is booted
INFO:nengo_spinnaker.utils.machine_control:Booting board
INFO:nengo_spinnaker.utils.machine_control:Checking that SpiNNaker board '172.16.1.2' is booted
INFO:nengo_spinnaker.utils.machine_control:Board is booted with SC&MP/SpiNNaker v1.33
DEBUG:nengo_spinnaker.simulator:Building model
INFO:nengo.cache:Cache miss [0618d9979a9656120af7b4be38e8954c3361f2ec].
INFO:nengo.cache:Cache miss [83c2feb72cf3c7279bea3f6412b3dce182f1065d].
INFO:nengo_spinnaker.simulator:Build took 0.084 seconds
DEBUG:nengo.builder.network:Network step 1: Building ensembles and nodes
DEBUG:nengo.builder.network:Network step 2: Building subnetworks
DEBUG:nengo.builder.network:Network step 3: Building connections
DEBUG:nengo.builder.network:Network step 4: Building probes
INFO:nengo_spinnaker.simulator:Building netlist
Building netlist seems to be the problem
@celiasmith reports:
This connection fails
inhib = nengo.Node([0]) #inhibit motor output
for ensemble in motor_ens.all_ensembles:
nengo.Connection(inhib, ensemble.neurons,
transform=[[-3]] * ensemble.n_neurons)
whereas this works
inhib = nengo.Node([0]) #inhibit motor output
inhib_ens = nengo.Ensemble(100,1)
for ensemble in motor_ens.all_ensembles:
nengo.Connection(inhib_ens, ensemble.neurons,
transform=[[-3]] * ensemble.n_neurons)
nengo.Connection(inhib, inhib_ens)
The error is:
Exception in thread Thread-9:
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 808, in __bootstrap_inner
self.run()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 761, in run
self.__target(*self.__args, **self.__kwargs)
File "/Users/celiasmi/Documents/nengo/nengo_gui/nengo_gui/viz.py", line 129, in runner
self.build()
File "/Users/celiasmi/Documents/nengo/nengo_gui/nengo_gui/viz.py", line 98, in build
self.sim = backend.Simulator(self.model)
File "/Users/celiasmi/Library/Python/2.7/lib/python/site-packages/nengo_spinnaker/simulator.py", line 97, in __init__
self.netlist = self.model.make_netlist(self.max_steps or 0)
File "/Users/celiasmi/Library/Python/2.7/lib/python/site-packages/nengo_spinnaker/builder/builder.py", line 328, in make_netlist
self, *args, **kwargs
File "/Users/celiasmi/Library/Python/2.7/lib/python/site-packages/nengo_spinnaker/operators/sdp_receiver.py", line 38, in make_vertices
raise NotImplementedError
NotImplementedError
The callback for received multicast packets is too slow and leads to network congestion. A fix The correct approach is to stick received packets into a queue and to have another thread process them outside of the interrupt. Moreover, the current multiple filter routing tables could be combined to decrease the amount of loop overheads and m-Trie table minimisation could be used to reduce the number of entries. (Alternatively, a more TCAM-like structure could be used and OC could be used to minimise this new table.)
The TCAM-like structure can be of the form: [(key, mask) -> [(filter routing entry, ...)]
There are some cases where there are lots of "equivalent" connections coming from Ensembles, e.g.:
nengo.Connection(a, b)
nengo.Connection(a, c)
It might be beneficial to combine these together (on SpiNNaker) so that the same value is sent for each connection, i.e, they will share a decoder matrix. As this is equivalent to using cached decoders I'm guessing there is no reason that this can't be done?
@tcstewar do you have any thoughts/concerns regarding this?
nengo_spinnaker needs updating to deal with nengo/nengo#677.
Here's a minimal example:
import nengo
import nengo_spinnaker
import numpy as np
model = nengo.Network()
with model:
def stim_func(t):
return np.sin(t), np.cos(t)
stim = nengo.Node(stim_func)
ea = nengo.networks.EnsembleArray(n_neurons=50, n_ensembles=2)
nengo.Connection(stim, ea.input)
sim = nengo_spinnaker.Simulator(model)
sim.run(1)
and here's the error:
Building finished in 0:00:01.
Traceback (most recent call last):
File "input_func_test.py", line 15, in <module>
sim.run(1)
File "/localhome/tcstewar/github/nengo_spinnaker/nengo_spinnaker/simulator.py", line 244, in run
self.run_steps(steps)
File "/localhome/tcstewar/github/nengo_spinnaker/nengo_spinnaker/simulator.py", line 250, in run_steps
self._run_steps(n_steps)
File "/localhome/tcstewar/github/nengo_spinnaker/nengo_spinnaker/simulator.py", line 300, in _run_steps
self.host_sim.step()
File "/localhome/tcstewar/github/nengo/nengo/simulator.py", line 308, in step
step_fn()
File "/localhome/tcstewar/github/nengo/nengo/builder/operator.py", line 626, in step_simpyfunc
y = fn(t.item(), *args) if t is not None else fn(*args)
File "/localhome/tcstewar/github/nengo_spinnaker/nengo_spinnaker/simulator.py", line 377, in func
return f(t, x)
File "/localhome/tcstewar/github/nengo_spinnaker/nengo_spinnaker/builder/node.py", line 340, in output
self.controller.set_node_output(self.target, value)
File "/localhome/tcstewar/github/nengo_spinnaker/nengo_spinnaker/node_io/ethernet.py", line 126, in set_node_output
c_value = np.dot(transform, c_value)
ValueError: shapes (1,1) and (2,) not aligned: 1 (dim 1) != 2 (dim 0)
This doesn't happen if the input goes straight to an Ensemble, or if the input is marked as function_of_time=True.
As per project-rig/rig#164. This will make pickling a netlist for Spaun easier (Python 2 only).
Should be calling toposort_flatten
with sort=False
, I think. More investigation required.
After discussion with @tcstewar it was suggested that there would be a change to the Simulator API to allow for repeated calls to run
and for continuous runs of indefinite period.
A simulator should be created with a period, this determines the amount of memory that will be allocated to store precomputed and probed data. If the period is None
then probing and precomputed values will be disabled; otherwise calls to simulate for longer than the specified period will be split into cycles of load data -> run simulation -> retrieve data. This is as was planned for in the design of the builder.
Initialised with | sim.run(1.0) |
sim.run(10.0) |
sim.run() |
Probes and precomputed functions |
---|---|---|---|---|
Simulator(model, period=5.0) |
✅ | ✅ but not guaranteed real-time | ✅ | |
Simulator(model, period=None) |
✅ | ✅ | ✅ sim.stop() should be called by another thread when done |
Additionally, the simulator should have a close
method which can take over the shut-down code necessary to clean up the SpiNNaker machine. This could be used with a context manager as well.
with sim:
sim.run(5.0)
# Do something
sim.run(1.0)
# Do something else
# Board has been cleared
When building this kind of connection:
def motor(t, x):
bot.motors([x[0], x[1], x[2], 0], msg_period=0.1)
motor_node = nengo.Node(motor, size_in=3)
nengo.Connection(motor_ens.output, motor_node, synapse=0.01)
No data gets to the node. And, if you try to plot the value it's always zero. However, this gets data to the node:
def motor(t, x):
bot.motors([x[0], x[1], x[2], 0], msg_period=0.1)
motor_node = nengo.Node(motor, size_in=3)
m_test = nengo.Ensemble(300,3)
nengo.Connection(motor_ens.output, m_test, synapse=0.01)
nengo.Connection(m_test,motor_node)
Hi
I am using a Spin5 local board.
Python:2.7
Numpy: 1.13.3
nengo: 2.6
nengo_spinnaker:0.4.0
on Ubuntu:14
when I try to "python learn_associations.py"
The example is unable to run with the following error.
File "/usr/local/lib/python2.7/dist-packages/nengo_spinnaker/builder/ensemble.py", line 166, in build_lif
max_rates = ensemble.sample(ens.max_rates, ens.n_neurons, rng=rng)
AttributError:'module' object has no attribute 'sample'
May I know what is wrong?
Rgds
Del
If I make a function_of_time Node and do a Connection to a sliced Ensemble, I get an error on build. For example:
import numpy as np
import nengo
model = nengo.Network()
with model:
stim = nengo.Node(lambda t: np.sin(t))
a = nengo.Ensemble(100, 2)
p = nengo.Probe(a, synapse=0.01)
nengo.Connection(stim, a[0])
import nengo_spinnaker
nengo_spinnaker.add_spinnaker_params(model.config)
model.config[stim].function_of_time = True
sim = nengo_spinnaker.SpiNNakerSimulator(model)
here is the error:
DEBUG:nengo.builder.network:Network step 1: Building ensembles and nodes
DEBUG:nengo.builder.network:Network step 2: Building subnetworks
DEBUG:nengo.builder.network:Network step 3: Building connections
DEBUG:nengo.builder.network:Network step 4: Building learning rules
DEBUG:nengo.builder.network:Network step 5: Building probes
INFO:nengo_spinnaker.simulator:Building netlist
Traceback (most recent call last):
File ".\test_node.py", line 23, in <module>
sim.run(10)
File "c:\users\terry\documents\github\nengo_spinnaker\nengo_spinnaker\simulator.py", line 58, in run
self.run_steps(steps)
File "c:\users\terry\documents\github\nengo_spinnaker\nengo_spinnaker\simulator.py", line 70, in run_steps
netlist = self.model.make_netlist(steps) # TODO remove steps!
File "c:\users\terry\documents\github\nengo_spinnaker\nengo_spinnaker\builder\builder.py", line 324, in make_netlist
self, *args, **kwargs
File "c:\users\terry\documents\github\nengo_spinnaker\nengo_spinnaker\operators\value_source.py", line 74, in make_vertices
outputs.append(np.array(output).reshape(n_steps, so))
ValueError: total size of new array must be unchanged
The MALLOC_AND_DIE calls in c_main don't cause it to die - spin1_exit just turns off the interrupts, all subsequent allocations continue to fail and the core goes into watchdog
I was playing around with some more learning on spinnaker, and I'm getting some discrepancies between nengo and nengo_spinnaker. Basically it looks like the number of neurons might not be getting taken into account in nengo_spinnaker, in nengo there's a part of the learning rule (which I belieeeeve is just 1/n_neurons) that makes sure that the learning will occur at the same rate no matter how many neurons there are. So that maybe might not be implemented?
One place where this came up was when I tried to increase the number of neurons for learning a more complex function, which resulted in oscillatory behaviour in the learning, but when I dropped the learning rate the change in weights became too small to get picked up by the system and so no learning occurred at all!
Here are some graphs, from nengo:
I'm not sure what's going on in the second half there, possibly completely unrelated to number of neurons. And actually as I'm looking at it it doesn't really look like the 2000 neuron population is just overshooting after that first bump...maybe things are saturating and then going to hell...I'm not sure. Here's the code I used:
import numpy as np
import nengo
import nengo_spinnaker
output = 0
model = nengo.Network()
with model:
node_in = nengo.Node(output=np.sin)
node_target = nengo.Node(output=lambda t: np.sin(t)**2)
ens100 = nengo.Ensemble(n_neurons=50, dimensions=1)
ens1000 = nengo.Ensemble(n_neurons=2000, dimensions=1)
ens200 = nengo.Ensemble(n_neurons=100, dimensions=1)
ens2000 = nengo.Ensemble(n_neurons=100, dimensions=1)
ens_target00 = nengo.Ensemble(n_neurons=100, dimensions=1)
ens_target000 = nengo.Ensemble(n_neurons=100, dimensions=1)
nengo.Connection(node_in, ens100)
nengo.Connection(node_in, ens1000)
learn_conn00 = nengo.Connection(ens100, ens200,
function = lambda x: 0,
learning_rule_type=nengo.PES(learning_rate=1e-4))
learn_conn000 = nengo.Connection(ens1000, ens2000,
function = lambda x: 0,
learning_rule_type=nengo.PES(learning_rate=1e-4))
nengo.Connection(node_target, ens_target00)
nengo.Connection(node_target, ens_target000)
nengo.Connection(ens200, ens_target00, transform=-1)
nengo.Connection(ens2000, ens_target000, transform=-1)
nengo.Connection(ens_target00, learn_conn00.learning_rule, transform=-1)
nengo.Connection(ens_target000, learn_conn000.learning_rule, transform=-1)
probe00 = nengo.Probe(ens200, synapse=.01)
probe000 = nengo.Probe(ens2000, synapse=.01)
probe_target = nengo.Probe(node_target)
nengo_spinnaker.add_spinnaker_params(model.config)
model.config[node_in].function_of_time = True
model.config[node_target].function_of_time = True
# sim = nengo_spinnaker.Simulator(model)
sim = nengo.Simulator(model)
sim.run(20.0)
sim.close()
import matplotlib.pyplot as plt
plt.plot(sim.trange(), sim.data[probe00])
plt.plot(sim.trange(), sim.data[probe000])
plt.plot(sim.trange(), sim.data[probe_target])
plt.show()
Also I am on the most recent nengo
and the new_ensemble-new-learning
branch of nengo_spinnaker
.
Large recording regions are the extreme case of this as they can take several megabytes of SDRAM, but essentially no DTCM. I've made the following hack to the LIF constraints, but it's not the best solution:
constraints = {
sdram_constraint: lambda s: regions.utils.sizeof_regions(
self.regions, s),
dtcm_constraint: lambda s: regions.utils.sizeof_regions(
self.regions[:-2], s), # **HACK**
cpu_constraint: cpu_usage,
}
This script uses a node to probe some data (the output of a circular convolution), but all it gets as input are 0 values. Using a regular probe works fine.
import nengo
import nengo.spa
import nengo_spinnaker
import numpy as np
import matplotlib.pyplot as plt
nengo.log(debug=True)
class Collector(object):
def __init__(self):
self.trange = []
self.data = []
def __call__(self, t, x):
self.trange.append(t)
self.data.append(np.squeeze(x))
d = 10
n_neurons = 50
rng = np.random.RandomState(123)
ctx = nengo.spa.SemanticPointer(d, rng)
ctx.make_unitary()
model = nengo.Network(seed=9023)
with model:
in_a = nengo.Node(output=nengo.spa.SemanticPointer(d, rng).v)
in_b = nengo.Node(output=ctx.v)
cconv = nengo.networks.CircularConvolution(n_neurons, d)
nengo.Connection(in_a, cconv.A)
nengo.Connection(in_b, cconv.B)
probe = Collector()
probe_node = nengo.Node(probe, size_in=d)
nengo.Connection(cconv.output, probe_node, synapse=0.01)
pr = nengo.Probe(cconv.output, synapse=0.01)
sim = nengo_spinnaker.Simulator(model)
sim.run(10.)
plt.subplot(2, 1, 1)
plt.plot(probe.trange, probe.data)
plt.subplot(2, 1, 2)
plt.plot(sim.trange(), sim.data[pr])
plt.show()
When using nengo_spinnaker along with nengo version 2.4.0, there is an error in ensemble.py file:
module 'ensemble' has no attribute 'sample'. When I downgraded nengo to version 2.2.0 the problem was solved.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.