Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid axon type bug #278

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c19fb0d
Ensure scipy.sparse is properly imported
hunse Oct 30, 2019
26140ee
Run tests in python 3.6 by default
hunse Oct 30, 2019
805778a
Support NxSDK 0.8.7
hunse Jul 3, 2019
ad9a353
Support NxSDK 0.9.0
hunse Oct 22, 2019
28322f2
Allow user to force precompute=False
hunse Oct 17, 2019
8c10b00
Add wall-time step timers to Simulator
hunse Oct 18, 2019
3b93155
Only create global spike generator if required
hunse Oct 17, 2019
1f00d55
Add host SNIP for faster communication
hunse Oct 23, 2019
24edd65
Larger channel packet size
hunse Oct 17, 2019
af847d3
Assert one block per core with learning
hunse Oct 30, 2019
5af0888
TMP: Added test_many_ensembles.py for speed test
hunse Oct 23, 2019
df56f68
fixup! Add host SNIP for faster communication
hunse Oct 30, 2019
f788346
Get core less in learn SNIP
hunse Nov 4, 2019
9210d6a
Reduce extra computation in host2chip_snips
hunse Nov 4, 2019
5f43078
Only sleep when creating socket connection
hunse Nov 4, 2019
af494a6
Simpler queueing in HostReceiveNode
hunse Nov 4, 2019
922c27b
Flip host2chip and host step order
hunse Oct 25, 2019
254944e
Turn off output check on helper nodes if possible
hunse Nov 4, 2019
cda7a5f
Eliminate slow hasattr call in collect receivers
hunse Nov 4, 2019
67c4927
WIP: Add simplified collect_receiver_info for one step
hunse Nov 4, 2019
5e75116
DecodeNeurons.get_ensemble user-friendly
hunse Nov 5, 2019
6773784
WIP: Add parallel_ensembles benchmark
hunse Nov 6, 2019
b2deba7
squash! WIP: Add parallel_ensembles benchmark
hunse Nov 6, 2019
836e9d2
BUG: Running parallel_ensemble.py results in invalid axon_type bug
hunse Nov 6, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .nengobones.yml
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ docs_conf_py:
analytics_id: UA-41658423-2

travis_yml:
python: 3.5.2
python: 3.6
global_vars:
NENGO_VERSION: nengo[tests]
NENGO_DL_VERSION: nengo-dl
Expand All @@ -452,10 +452,11 @@ travis_yml:
NENGO_VERSION: git+https://github.com/nengo/nengo.git#egg=nengo[tests]
NENGO_DL_VERSION: git+https://github.com/nengo/nengo-dl.git#egg=nengo-dl
- script: hardware
python: 3.5.2 # nxsdk requires 3.5.2
env:
NENGO_VERSION: git+https://github.com/nengo/nengo.git#egg=nengo[tests]
NENGO_DL_VERSION: git+https://github.com/nengo/nengo-dl.git#egg=nengo-dl
NXSDK_VERSION: 0.8.5
NXSDK_VERSION: 0.9
- script: docs
env:
NENGO_VERSION: git+https://github.com/nengo/nengo.git#egg=nengo[tests]
Expand All @@ -472,7 +473,7 @@ ci_scripts:
- $NENGO_VERSION
- $NENGO_DL_VERSION
- jupyter
- numpy
- numpy>=1.14 # avoid the default-installed 1.13 on TravisCI
coverage: true
nengo_tests: true
- template: static
Expand Down
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Automatically generated by nengo-bones, do not edit this file directly

language: python
python: 3.5.2
python: 3.6
notifications:
email:
on_success: change
Expand Down Expand Up @@ -41,8 +41,9 @@ jobs:
env:
NENGO_VERSION="git+https://github.com/nengo/nengo.git#egg=nengo[tests]"
NENGO_DL_VERSION="git+https://github.com/nengo/nengo-dl.git#egg=nengo-dl"
NXSDK_VERSION="0.8.5"
NXSDK_VERSION="0.9"
SCRIPT="hardware"
python: 3.5.2
-
env:
NENGO_VERSION="git+https://github.com/nengo/nengo.git#egg=nengo[tests]"
Expand Down
4 changes: 4 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Release history
(`#240 <https://github.com/nengo/nengo-loihi/pull/240>`__)
- A more informative error message is raised if any encoders contain NaNs.
(`#251 <https://github.com/nengo/nengo-loihi/pull/251>`__)
- Nengo Loihi now supports NxSDK version 0.9.0.
(`#255 <https://github.com/nengo/nengo-loihi/pull/255>`__)

**Changed**

Expand All @@ -39,6 +41,8 @@ Release history
(`#226 <https://github.com/nengo/nengo-loihi/pull/226>`__)
- The ``scipy`` package is now required to run Nengo Loihi.
(`#240 <https://github.com/nengo/nengo-loihi/pull/240>`__)
- Nengo Loihi now requires NxSDK version 0.8.7.
(`#234 <https://github.com/nengo/nengo-loihi/pull/234>`__)

0.8.0 (June 23, 2019)
=====================
Expand Down
172 changes: 172 additions & 0 deletions docs/benchmarks/parallel_ensembles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import cProfile
import timeit

import matplotlib.pyplot as plt
import nengo
import nengo_loihi
from nengo_loihi import decode_neurons
import numpy as np

rng = np.random.RandomState(1)
seed = rng.randint(0, 2**31)

LoihiEmulator = lambda net: nengo_loihi.Simulator(net, target="sim")
LoihiSimulator = lambda net: nengo_loihi.Simulator(
net, target="loihi", hardware_options=dict(snip_max_spikes_per_step=300),
)
NengoSimulator = lambda net: nengo.Simulator(net)

Simulator = LoihiSimulator

funnel_input = False
funnel_output = True
learning = False
profile = False
#profile = True

simtime = 10

#n_input = 6
#n_output = 3
n_input = 10
n_output = 5

#n_neurons = 10
#n_neurons = 100
n_neurons = 400
#n_neurons = 1000

#n_ensembles = 1
#n_ensembles = 3
n_ensembles = 20

#pes_learning_rate = 5e-9
pes_learning_rate = 5e-6
#pes_learning_rate = 5e-4

# synapse time constants
tau_input = 0.01
tau_error = 0.01
tau_output = 0.01

encoders_dist = nengo.dists.UniformHypersphere(surface=True)
encoders = encoders_dist.sample(n_neurons * n_ensembles, n_input, rng=rng)
encoders = encoders.reshape(n_ensembles, n_neurons, n_input)

input_freq = np.pi
input_phases = (1 / n_input) * np.arange(n_input)

# desired transform between input and output
assert n_input % n_output == 0
inout_transform = np.repeat(np.eye(n_output), n_input / n_output, axis=1)
inout_transform /= inout_transform.sum(axis=1, keepdims=True)

net = nengo.Network(seed=seed)
net.config[nengo.Ensemble].neuron_type = nengo.LIF()
net.config[nengo.Ensemble].intercepts = nengo.dists.Uniform(-1, 0.5)
net.config[nengo.Ensemble].max_rates = nengo.dists.Uniform(100, 200)
# net.config[nengo.Connection].synapse = None

with net:
error_rng = np.random.RandomState(5)

def ctrl_func(t, u_adapt):
inputs = np.sin(input_freq*t + 2*np.pi*input_phases)

target_output = np.dot(inout_transform, inputs)
errors = u_adapt - target_output

return inputs.tolist() + errors.tolist()

ctrl = nengo.Node(ctrl_func, size_in=n_output, size_out=n_input+n_output, label="ctrl")
ctrl_probe = nengo.Probe(ctrl)

input = ctrl[:n_input]
error = ctrl[n_input:]
output = ctrl

inp2ens_transform = None
if funnel_input:
input_decodeneurons = decode_neurons.Preset10DecodeNeurons()
onchip_input = input_decodeneurons.get_ensemble(dim=n_input)
nengo.Connection(input, onchip_input, synapse=None)
inp2ens_transform = np.hstack(
[np.eye(n_input), -np.eye(n_input)] * input_decodeneurons.pairs_per_dim
)
input = onchip_input

if funnel_output:
output_decodeneurons = decode_neurons.Preset10DecodeNeurons()
onchip_output = output_decodeneurons.get_ensemble(dim=n_output)
out2ctrl_transform = np.hstack(
[np.eye(n_output), -np.eye(n_output)] * output_decodeneurons.pairs_per_dim
) / 2000.
nengo.Connection(
onchip_output.neurons,
output,
transform=out2ctrl_transform,
synapse=tau_output,
)
output = onchip_output

for ii in range(n_ensembles):
ens = nengo.Ensemble(
n_neurons=n_neurons,
dimensions=n_input,
radius=np.sqrt(n_input),
encoders=encoders[ii],
label="ens%02d" % ii,
)

if inp2ens_transform is not None:
inp2ens_transform_ii = np.dot(encoders[ii], inp2ens_transform)
nengo.Connection(
input.neurons,
ens.neurons,
transform=inp2ens_transform_ii,
synapse=tau_input
)
else:
nengo.Connection(input, ens, synapse=tau_input)

conn_kwargs = dict()
if learning:
conn_kwargs["transform"] = rng.uniform(-0.01, 0.01, size=(n_output, n_input))
conn_kwargs["learning_rule_type"] = nengo.PES(
pes_learning_rate, pre_synapse=tau_error,
)
else:
conn_kwargs["transform"] = inout_transform / n_ensembles

conn = nengo.Connection(ens, output, **conn_kwargs)

if learning:
nengo.Connection(error, conn.learning_rule, synapse=None)


with Simulator(net) as sim:
sim.run(0.001) # eliminate any extra startup from timing

steps = sim.n_steps
timer = timeit.default_timer()
if profile:
cProfile.runctx("sim.run(%s)" % simtime, globals(), locals(), sort="cumtime")
else:
sim.run(simtime)
timer = timeit.default_timer() - timer
steps = sim.n_steps - steps
print('Run time/step: %0.2f ms' % (1000 * timer / steps))

inputs = sim.data[ctrl_probe][:, :n_input]
targets = np.dot(inputs, inout_transform.T)
errors = sim.data[ctrl_probe][:, n_input:]
outputs = errors + targets

error_steps = min(sim.n_steps, 2000)
start_error = np.abs(errors[:error_steps]).mean()
end_error = np.abs(errors[-error_steps:]).mean()
print("Error: start %0.3f, end %0.3f" % (start_error, end_error))

plt.plot(sim.trange(), targets, ":")
plt.plot(sim.trange(), outputs)
plt.savefig("parallel_ensembles.pdf")
5 changes: 4 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@

# -- sphinx
nitpicky = True
exclude_patterns = ["_build", "**/.ipynb_checkpoints"]
exclude_patterns = [
"_build",
"**/.ipynb_checkpoints",
]
linkcheck_timeout = 30
source_suffix = ".rst"
source_encoding = "utf-8"
Expand Down
2 changes: 1 addition & 1 deletion nengo_loihi/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from nengo.exceptions import BuildError

import numpy as np
import scipy
import scipy.sparse

from nengo_loihi.nxsdk_obfuscation import d

Expand Down
4 changes: 2 additions & 2 deletions nengo_loihi/builder/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from nengo.exceptions import BuildError, ValidationError
from nengo.solvers import NoSolver, Solver
import numpy as np
import scipy
import scipy.sparse

from nengo_loihi.block import Axon, LoihiBlock, Probe, Synapse
from nengo_loihi.builder.builder import Builder
Expand Down Expand Up @@ -185,7 +185,7 @@ def build_host_to_chip(model, conn):
build_chip_connection(model, receive2post)

logger.debug("Creating DecodeNeuron ensemble for %s", conn)
ens = model.node_neurons.get_ensemble(dim)
ens = model.node_neurons.get_ensemble(dim, is_input=True, add_to_container=False)
ens.label = None if conn.label is None else "%s_ens" % conn.label
_inherit_seed(host, ens, model, conn)
host.build(ens)
Expand Down
35 changes: 20 additions & 15 deletions nengo_loihi/builder/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
class HostSendNode(Node):
"""For sending host->chip messages"""

def __init__(self, dimensions, label=Default):
def __init__(self, dimensions, label=Default, check_output=False):
self.queue = []
super(HostSendNode, self).__init__(
self.update, size_in=dimensions, size_out=0, label=label
)
if hasattr(self, "check_output"):
self.check_output = check_output

def update(self, t, x):
assert len(self.queue) == 0 or t > self.queue[-1][0]
Expand All @@ -23,20 +25,18 @@ def update(self, t, x):
class HostReceiveNode(Node):
"""For receiving chip->host messages"""

def __init__(self, dimensions, label=Default):
def __init__(self, dimensions, label=Default, check_output=False):
self.queue = [(0, np.zeros(dimensions))]
self.queue_index = 0
super(HostReceiveNode, self).__init__(
self.update, size_in=0, size_out=dimensions, label=label
)
if hasattr(self, "check_output"):
self.check_output = check_output

def update(self, t):
while (
len(self.queue) > self.queue_index + 1
and self.queue[self.queue_index][0] < t
):
self.queue_index += 1
return self.queue[self.queue_index][1]
t1, x = self.queue[-1]
assert t >= t1
return x

def receive(self, t, x):
self.queue.append((t, x))
Expand All @@ -48,6 +48,7 @@ class ChipReceiveNode(Node):
def __init__(self, dimensions, size_out, label=Default):
self.raw_dimensions = dimensions
self.spikes = []
self.error_target = None
self.spike_input = None # set by builder
super(ChipReceiveNode, self).__init__(
self.update, size_in=0, size_out=size_out, label=label
Expand All @@ -64,10 +65,11 @@ def receive(self, t, x):
def update(self, t):
raise SimulationError("ChipReceiveNodes should not be run")

def collect_errors(self):
return ()

def collect_spikes(self):
assert self.spike_input is not None
for t, x in self.spikes:
yield (self.spike_input, t, x)
return self.spikes


class ChipReceiveNeurons(ChipReceiveNode):
Expand All @@ -80,8 +82,9 @@ def __init__(self, dimensions, neuron_type=None, label=Default):

class PESModulatoryTarget:
def __init__(self, target):
self.target = target
self.errors = OrderedDict()
self.error_target = target
self.spike_input = None

def clear(self):
self.errors.clear()
Expand All @@ -94,5 +97,7 @@ def receive(self, t, x):
self.errors[t] = np.array(x)

def collect_errors(self):
for t, x in self.errors.items():
yield (self.target, t, x)
return self.errors.items()

def collect_spikes(self):
return ()
2 changes: 1 addition & 1 deletion nengo_loihi/builder/sparse_matrix.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import numpy as np
import scipy
import scipy.sparse


def expand_matrix(matrix, shape):
Expand Down
2 changes: 1 addition & 1 deletion nengo_loihi/builder/tests/test_sparse_matrix.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import numpy as np
import pytest
import scipy
import scipy.sparse

from nengo_loihi.builder.sparse_matrix import (
expand_matrix,
Expand Down
Loading