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

Speeding up snips by communicating less often #26

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
3 changes: 3 additions & 0 deletions nengo_loihi/loihi_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,9 @@ def create_io_snip(self, io_steps):
for core in chip.cores:
for inp, cx_ids in core.iterate_inputs():
axon_ids = inp.axon_ids[0]
# axon_ids are in pairs, due to the positive and
# negative channels, but we just want the number
# of values to send
assert len(axon_ids) % 2 == 0
n_inputs += len(axon_ids) // 2

Expand Down
14 changes: 12 additions & 2 deletions nengo_loihi/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,12 +460,22 @@ def determine_spike_targets(self):
inp = receiver.cx_spike_input
assert len(inp.axon_ids) == 1 # TODO: handle len>1
axon_ids = inp.axon_ids[0]
# the first half are the positive channels and the second
# half are the negative channels
half = len(axon_ids)//2
for i in range(len(axon_ids)//2):
# we currently only handle one Loihi chip, so assert
# that chip_id is zero
assert axon_ids[i][0] == 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the chip ID, right? Maybe put a "chip_id must be zero" message with the assertion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment added :)

# the core_ids of the positive and negative channels
# should be the same
assert axon_ids[i][1] == axon_ids[half+i][1]
spike_targets.extend((axon_ids[i][1], axon_ids[i][2],
axon_ids[half+i][2]))

spike_targets.extend((
axon_ids[i][1], # the core for this input
axon_ids[i][2], # axon_id for the positive channel
axon_ids[half+i][2] # axon_id for the negative channel
))
return spike_targets

def handle_host2chip_communications(self): # noqa: C901
Expand Down
26 changes: 16 additions & 10 deletions nengo_loihi/snips/nengo_io.c.template
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ void nengo_io(runState *s) {
printf("initializing\n");
for (int i=0; i<N_INPUTS; i++) {
readChannel(inChannel, spike, 3);
s->userData[IDX_SPIKE_TARGETS+(i*3)+0] = spike[0];
s->userData[IDX_SPIKE_TARGETS+(i*3)+1] = spike[1];
s->userData[IDX_SPIKE_TARGETS+(i*3)+2] = spike[2];
s->userData[IDX_SPIKE_TARGETS+(i*3)+0] = spike[0]; // core id
s->userData[IDX_SPIKE_TARGETS+(i*3)+1] = spike[1]; // pos axon
s->userData[IDX_SPIKE_TARGETS+(i*3)+2] = spike[2]; // neg axon
printf(" spike target %d: (%d %d %d)\n",
i, spike[0], spike[1], spike[2]);
}
Expand All @@ -58,11 +58,15 @@ void nengo_io(runState *s) {
// printf("count %d\n", count[0]);

// --- read input values (once every IO_STEPS)
if (s->time % IO_STEPS == 0) {
// Note that we do this at the *start* of an IO_STEP period (since
// s->time starts at 1), so that we don't have a period at the beginning
// of the simulation where we are ignoring the input.
if (s->time % IO_STEPS == 1 % IO_STEPS) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the same as (IO_STEPS==1) || (s->time % IO_STEPS == 1)? Currently we do it one way here and another way down below. I'd keep it consistent. Also, as elegant as this way is, I think I prefer the explicit OR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I didn't even notice I'd solved that puzzle before.... :) Yes, those are meant to be the same, and I agree that the explicit OR is clearer than the elegant mod-comparison thing. :) I've switched it to the explicit approach.

for (int i=0; i < N_INPUTS; i++) {
readChannel(inChannel, spike, 1);
//printf(" %d: stim value %d.%d\n", s->time, i, spike[0]);
value[i] = spike[0];
value[i] = spike[0]; // discretized version of the real value
// to be used as input
}

// Communicate with learning snip
Expand Down Expand Up @@ -106,13 +110,15 @@ void nengo_io(runState *s) {
}
}

// --- write output values (once every IO_STEPS)
if ((IO_STEPS==1) || (s->time % IO_STEPS == 1)) {
output[0] = s->time;
if (N_OUTPUTS > 0) {
// --- write output values (once every IO_STEPS)
if ((IO_STEPS==1) || (s->time % IO_STEPS == 1)) {
output[0] = s->time;
{% for n_out, core, cx in probes %}
output[{{ n_out }}] = core{{ core }}->cx_state[{{ cx }}].V;
output[{{ n_out }}] = core{{ core }}->cx_state[{{ cx }}].V;
{% endfor %}

writeChannel(outChannel, output, N_OUTPUTS);
writeChannel(outChannel, output, N_OUTPUTS);
}
}
}
2 changes: 2 additions & 0 deletions nengo_loihi/splitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ def split(model, inter_rate, inter_n, # noqa: C901
receive = ChipReceiveNode(dim * 2, size_out=dim)
nengo.Connection(receive, c.post, synapse=c.synapse)
with host:
# TODO: check whether this max_rate makes sense and
# whether it should be dependent on dt
max_rate = inter_rate * inter_n
assert max_rate <= 1000

Expand Down