ctn-archive / nengo_spinnaker_2014

SpiNNaker backend for Nengo -- now obsolete. See instead https://github.com/project-rig/nengo_spinnaker
MIT License
0 stars 1 forks source link

Migration to new partition/place/route/comms toolchain, upstream changes. #103

Closed mundya closed 9 years ago

mundya commented 10 years ago

This is a horribly huge PR, sadly everything kind of needed to happen at once; I will rewrite history before merging. :japanese_ogre:

New toolchain

Todo:

A new vertex model is built for this purpose, the following objects require new vertices constructing:

A big part of this rewrite is some changes toward formalising the on-host model of connections between Nengo objects. The intent is to reduce the transmission of "duplicated" packets on the SpiNNaker machine as this incurs higher than necessary memory and network utilisation. This reduction is achieved through combining compatible connections. Compatible connections originate from the same object, live in the same keyspace and transmit the same data (that is, have the same transform and function*).

For example, the code below will result in the "tree":

(a) ----- (conn1 & 2 combined) -----> (c)
                               \----> (d)

(b) ----- (conn3) ------------------> (c)
 |
 +------- (conn4) ------------------> (d)
 |
 \------- (conn5 & 6) --------------> (c)
                      \-------------> (d)

The code in connections/connection_tree.py represents the high-level class for building up trees of connections. Correct aliasing of connection types is based on breaking each Connection object into a ReducedOutgoingConnection and a ReducedIncomingConnection; each type stores the minimum of information required when transmitting or receiving packets respectively.

The connection "tree" is generated by taking each connection in turn, breaking it into an outgoing and an incoming form, and indexing these such that: originating object -> [outgoing connection -> [incoming connections]]. Aliasing connections relies on correct definition of the __hash__ and __eq__ methods.

*Function equivalence is tricky. For connections from ensembles we can check that functions are equivalent by checking they have the same id, or by evaluating them at all evaluation points and checking for the equivalence of the outputs. For connections from other objects we can only check id (or the bytecode :skull:). Some interesting results follow:

with nengo.Network(label='Connection Sharing') as model:
    a = nengo.Ensemble(100, 1)
    b = nengo.Node(lambda t: t**2, size_in=0, size_out=1)
    c = nengo.Ensemble(100, 1)
    d = nengo.Ensemble(100, 1)

    # These two connections will be considered equivalent (shared)
    conn1 = nengo.Connection(a, c, function=lambda x: x**2)
    conn2 = nengo.Connection(a, d, function=lambda x: x**2)

    # Whereas these will not
    conn3 = nengo.Connection(b, c, function=lambda x: x**2)
    conn4 = nengo.Connection(b, d, function=lambda x: x**2)

    # But these will
    squared = lambda x: x**2
    conn5 = nengo.Connection(b, c, function=squared)
    conn6 = nengo.Connection(b, d, function=squared)

Upstream changes

I've been trying to keep up with changes in Nengo, thorough testing will be necessary... I'm a little concerned about learning rules.

Other TODO