def assign_xyzp_keys(nets):
    """Return a dictionary mapping a net to a unique key indicating the XYZP
    co-ordinate of the source of the net.
    """
    # Create the XYZP-formatted bit field
    xyzp_bf = BitField()
    xyzp_bf.add_field("x", length=8, start_at=24)
    xyzp_bf.add_field("y", length=8, start_at=16)
    xyzp_bf.add_field("z", length=8, start_at=8)
    xyzp_bf.add_field("p", length=5, start_at=3)
    xyzp_bf.assign_fields()  # Fix the bitfield sizing

    # Prepare to store the nets and keys
    net_keys = dict()

    # For each net look at the placement of the source vertex and hence
    # generate a key.
    for net in nets:
        # Get the originating co-ordinates
        x, y, p = net.source

        # Get the minimal xyz co-ordinate
        x, y, z = minimise_xyz(to_xyz((x, y)))

        # Generate the key and mask
        bf = xyzp_bf(x=x, y=y, z=abs(z), p=p)
        net_keys[net] = bf.get_value(), bf.get_mask()

    return net_keys
Exemple #2
0
def assign_xyzp_keys(nets):
    """Return a dictionary mapping a net to a unique key indicating the XYZP
    co-ordinate of the source of the net.
    """
    # Create the XYZP-formatted bit field
    xyzp_bf = BitField()
    xyzp_bf.add_field("x", length=8, start_at=24)
    xyzp_bf.add_field("y", length=8, start_at=16)
    xyzp_bf.add_field("z", length=8, start_at=8)
    xyzp_bf.add_field("p", length=5, start_at=3)
    xyzp_bf.assign_fields()  # Fix the bitfield sizing

    # Prepare to store the nets and keys
    net_keys = dict()

    # For each net look at the placement of the source vertex and hence
    # generate a key.
    for net in nets:
        # Get the originating co-ordinates
        x, y, p = net.source

        # Get the minimal xyz co-ordinate
        x, y, z = minimise_xyz(to_xyz((x, y)))

        # Generate the key and mask
        bf = xyzp_bf(x=x, y=y, z=abs(z), p=p)
        net_keys[net] = bf.get_value(), bf.get_mask()

    return net_keys
def make_routing_tables():
    # Create a perfect SpiNNaker machine to build against
    machine = Machine(12, 12)

    # Assign a vertex to each of the 17 application cores on each chip
    vertices = OrderedDict(
        ((x, y, p), object()) for x, y in machine for p in range(1, 18)
    )

    # Generate the vertex resources, placements and allocations (required for
    # routing)
    vertices_resources = OrderedDict(
        (vertex, {Cores: 1}) for vertex in itervalues(vertices)
    )
    placements = OrderedDict(
        (vertex, (x, y)) for (x, y, p), vertex in iteritems(vertices)
    )
    allocations = OrderedDict(
        (vertex, {Cores: slice(p, p+1)}) for (x, y, p), vertex in
        iteritems(vertices)
    )

    # Compute the distance dependent probabilities - this is a geometric
    # distribution such that each core has a 50% chance of being connected to
    # each core on the same chip, 25% on chips one hop away, 12.5% on chips two
    # hops away, etc.
    p = 0.5
    probs = {d: p*(1 - p)**d for d in
             range(max(machine.width, machine.height))}

    p = 0.3
    dprobs = {d: p*(1 - p)**d for d in
              range(max(machine.width, machine.height))}

    # Compute offsets to get to centroids
    vector_centroids = list()
    for d in (5, 6, 7):
        for i in range(d + 1):
            for j in range(d + 1 - i):
                vector_centroids.append((i, j, d - i - j))

    # Make the nets, each vertex is connected with distance dependent
    # probability to other vertices.
    random.seed(123)
    nets = OrderedDict()
    for source_coord, source in iteritems(vertices):
        # Convert source_coord to xyz form
        source_coord_xyz = minimise_xyz(to_xyz(source_coord[:-1]))

        # Add a number of centroids
        x, y, z = source_coord_xyz
        possible_centroids = [minimise_xyz((x + i, y + j, z + k)) for
                              i, j, k in vector_centroids]
        n_centroids = random.choice(17*(0, ) + (1, 1) + (2, ))
        centroids = random.sample(possible_centroids, n_centroids)

        # Construct the sinks list
        sinks = list()
        for sink_coord, sink in iteritems(vertices):
            # Convert sink_coord to xyz form
            sink_coord = minimise_xyz(to_xyz(sink_coord[:-1]))

            # Get the path length to the original source
            dist = shortest_torus_path_length(source_coord_xyz, sink_coord,
                                              machine.width, machine.height)
            if random.random() < probs[dist]:
                sinks.append(sink)
                continue

            # See if the sink is connected to the centre of any of the
            # centroids.
            for coord in centroids:
                dist = shortest_torus_path_length(
                    coord, sink_coord, machine.width, machine.height
                )

                if random.random() < dprobs[dist]:
                    sinks.append(sink)
                    break

        # Add the net
        nets[source_coord] = Net(source, sinks)

    rig_nets = list(itervalues(nets))  # Just the nets

    # Determine how many bits to use in the keys
    xyp_fields = BitField(32)
    xyp_fields.add_field("x", length=8, start_at=24)
    xyp_fields.add_field("y", length=8, start_at=16)
    xyp_fields.add_field("p", length=5, start_at=11)

    xyzp_fields = BitField(32)
    xyzp_fields.add_field("x", length=8, start_at=24)
    xyzp_fields.add_field("y", length=8, start_at=16)
    xyzp_fields.add_field("z", length=8, start_at=8)
    xyzp_fields.add_field("p", length=5, start_at=3)

    hilbert_fields = BitField(32)
    hilbert_fields.add_field("index", length=16, start_at=16)
    hilbert_fields.add_field("p", length=5, start_at=11)

    random.seed(321)
    rnd_fields = BitField(32)
    rnd_fields.add_field("rnd", length=12, start_at=20)
    rnd_seen = set()

    # Generate the routing keys
    net_keys_xyp = OrderedDict()
    net_keys_xyzp = OrderedDict()
    net_keys_hilbert = OrderedDict()
    net_keys_rnd = OrderedDict()
    for i, (x, y) in enumerate(chip for chip in hilbert_chip_order(machine) if
                               chip in machine):
        # Add the key for each net from each processor
        for p in range(1, 18):
            # Get the net
            net = nets[(x, y, p)]

            # Construct the xyp key/mask
            net_keys_xyp[net] = xyp_fields(x=x, y=y, p=p)

            # Construct the xyzp mask
            x_, y_, z_ = minimise_xyz(to_xyz((x, y)))
            net_keys_xyzp[net] = xyzp_fields(x=x_, y=y_, z=abs(z_), p=p)

            # Construct the Hilbert key/mask
            net_keys_hilbert[net] = hilbert_fields(index=i, p=p)

            # Construct the random 12 bit value field
            val = None
            while val is None or val in rnd_seen:
                val = random.getrandbits(12)
            rnd_seen.add(val)
            net_keys_rnd[net] = rnd_fields(rnd=val)

    # Route the network and then generate the routing tables
    constraints = list()
    print("Routing...")
    routing_tree = route(vertices_resources, rig_nets, machine, constraints,
                         placements, allocations)

    # Write the routing tables to file
    for fields, desc in ((net_keys_xyp, "xyp"),
                         (net_keys_xyzp, "xyzp"),
                         (net_keys_hilbert, "hilbert"),
                         (net_keys_rnd, "rnd")):
        print("Getting keys and masks...")
        keys = OrderedDict(
            (net, (bf.get_value(), bf.get_mask())) for net, bf in
            iteritems(fields)
        )

        print("Constructing routing tables for {}...".format(desc))
        tables = routing_tree_to_tables(routing_tree, keys)
        print([len(x) for x in itervalues(tables)])

        print("Writing to file...")
        fn = "uncompressed/centroid_{}_{}_{}.bin".format(
            machine.width, machine.height, desc)
        with open(fn, "wb+") as f:
            dump_routing_tables(f, tables)
Exemple #4
0
def make_routing_tables():
    # Create a perfect SpiNNaker machine to build against
    machine = Machine(12, 12)

    # Assign a vertex to each of the 17 application cores on each chip
    vertices = OrderedDict(
        ((x, y, p), object()) for x, y in machine for p in range(1, 18))

    # Generate the vertex resources, placements and allocations (required for
    # routing)
    vertices_resources = OrderedDict((vertex, {
        Cores: 1
    }) for vertex in itervalues(vertices))
    placements = OrderedDict(
        (vertex, (x, y)) for (x, y, p), vertex in iteritems(vertices))
    allocations = OrderedDict((vertex, {
        Cores: slice(p, p + 1)
    }) for (x, y, p), vertex in iteritems(vertices))

    # Compute the distance dependent probabilities - this is a geometric
    # distribution such that each core has a 50% chance of being connected to
    # each core on the same chip, 25% on chips one hop away, 12.5% on chips two
    # hops away, etc.
    p = 0.5
    probs = {
        d: p * (1 - p)**d
        for d in range(max(machine.width, machine.height))
    }

    p = 0.3
    dprobs = {
        d: p * (1 - p)**d
        for d in range(max(machine.width, machine.height))
    }

    # Compute offsets to get to centroids
    vector_centroids = list()
    for d in (5, 6, 7):
        for i in range(d + 1):
            for j in range(d + 1 - i):
                vector_centroids.append((i, j, d - i - j))

    # Make the nets, each vertex is connected with distance dependent
    # probability to other vertices.
    random.seed(123)
    nets = OrderedDict()
    for source_coord, source in iteritems(vertices):
        # Convert source_coord to xyz form
        source_coord_xyz = minimise_xyz(to_xyz(source_coord[:-1]))

        # Add a number of centroids
        x, y, z = source_coord_xyz
        possible_centroids = [
            minimise_xyz((x + i, y + j, z + k)) for i, j, k in vector_centroids
        ]
        n_centroids = random.choice(17 * (0, ) + (1, 1) + (2, ))
        centroids = random.sample(possible_centroids, n_centroids)

        # Construct the sinks list
        sinks = list()
        for sink_coord, sink in iteritems(vertices):
            # Convert sink_coord to xyz form
            sink_coord = minimise_xyz(to_xyz(sink_coord[:-1]))

            # Get the path length to the original source
            dist = shortest_torus_path_length(source_coord_xyz, sink_coord,
                                              machine.width, machine.height)
            if random.random() < probs[dist]:
                sinks.append(sink)
                continue

            # See if the sink is connected to the centre of any of the
            # centroids.
            for coord in centroids:
                dist = shortest_torus_path_length(coord, sink_coord,
                                                  machine.width,
                                                  machine.height)

                if random.random() < dprobs[dist]:
                    sinks.append(sink)
                    break

        # Add the net
        nets[source_coord] = Net(source, sinks)

    rig_nets = list(itervalues(nets))  # Just the nets

    # Determine how many bits to use in the keys
    xyp_fields = BitField(32)
    xyp_fields.add_field("x", length=8, start_at=24)
    xyp_fields.add_field("y", length=8, start_at=16)
    xyp_fields.add_field("p", length=5, start_at=11)

    xyzp_fields = BitField(32)
    xyzp_fields.add_field("x", length=8, start_at=24)
    xyzp_fields.add_field("y", length=8, start_at=16)
    xyzp_fields.add_field("z", length=8, start_at=8)
    xyzp_fields.add_field("p", length=5, start_at=3)

    hilbert_fields = BitField(32)
    hilbert_fields.add_field("index", length=16, start_at=16)
    hilbert_fields.add_field("p", length=5, start_at=11)

    random.seed(321)
    rnd_fields = BitField(32)
    rnd_fields.add_field("rnd", length=12, start_at=20)
    rnd_seen = set()

    # Generate the routing keys
    net_keys_xyp = OrderedDict()
    net_keys_xyzp = OrderedDict()
    net_keys_hilbert = OrderedDict()
    net_keys_rnd = OrderedDict()
    for i, (x, y) in enumerate(chip for chip in hilbert_chip_order(machine)
                               if chip in machine):
        # Add the key for each net from each processor
        for p in range(1, 18):
            # Get the net
            net = nets[(x, y, p)]

            # Construct the xyp key/mask
            net_keys_xyp[net] = xyp_fields(x=x, y=y, p=p)

            # Construct the xyzp mask
            x_, y_, z_ = minimise_xyz(to_xyz((x, y)))
            net_keys_xyzp[net] = xyzp_fields(x=x_, y=y_, z=abs(z_), p=p)

            # Construct the Hilbert key/mask
            net_keys_hilbert[net] = hilbert_fields(index=i, p=p)

            # Construct the random 12 bit value field
            val = None
            while val is None or val in rnd_seen:
                val = random.getrandbits(12)
            rnd_seen.add(val)
            net_keys_rnd[net] = rnd_fields(rnd=val)

    # Route the network and then generate the routing tables
    constraints = list()
    print("Routing...")
    routing_tree = route(vertices_resources, rig_nets, machine, constraints,
                         placements, allocations)

    # Write the routing tables to file
    for fields, desc in ((net_keys_xyp, "xyp"), (net_keys_xyzp, "xyzp"),
                         (net_keys_hilbert, "hilbert"), (net_keys_rnd, "rnd")):
        print("Getting keys and masks...")
        keys = OrderedDict((net, (bf.get_value(), bf.get_mask()))
                           for net, bf in iteritems(fields))

        print("Constructing routing tables for {}...".format(desc))
        tables = routing_tree_to_tables(routing_tree, keys)
        print([len(x) for x in itervalues(tables)])

        print("Writing to file...")
        fn = "uncompressed/centroid_{}_{}_{}.bin".format(
            machine.width, machine.height, desc)
        with open(fn, "wb+") as f:
            dump_routing_tables(f, tables)
Exemple #5
0
def make_routing_tables():
    # Create a perfect SpiNNaker machine to build against
    machine = Machine(12, 12)

    # Assign a vertex to each of the 17 application cores on each chip
    vertices = OrderedDict(
        ((x, y, p), object()) for x, y in machine for p in range(1, 18)
    )

    # Generate the vertex resources, placements and allocations (required for
    # routing)
    vertices_resources = OrderedDict(
        (vertex, {Cores: 1}) for vertex in itervalues(vertices)
    )
    placements = OrderedDict(
        (vertex, (x, y)) for (x, y, p), vertex in iteritems(vertices)
    )
    allocations = OrderedDict(
        (vertex, {Cores: slice(p, p+1)}) for (x, y, p), vertex in
        iteritems(vertices)
    )

    # Compute the distance dependent probabilities
    probs = {d: .5*math.exp(-.65*d) for d in
             range(max(machine.width, machine.height))}

    # Make the nets, each vertex is connected with distance dependent
    # probability to other vertices.
    random.seed(123)
    nets = OrderedDict()
    for source_coord, source in iteritems(vertices):
        # Convert source_coord to xyz form
        source_coord_xyz = minimise_xyz(to_xyz(source_coord[:-1]))

        # Construct the sinks list
        sinks = list()
        for sink_coord, sink in iteritems(vertices):
            # Convert sink_coord to xyz form
            sink_coord = minimise_xyz(to_xyz(sink_coord[:-1]))

            # Get the path length
            dist = shortest_torus_path_length(source_coord_xyz, sink_coord,
                                              machine.width, machine.height)

            if random.random() < probs[dist]:
                sinks.append(sink)

        # Add the net
        nets[source_coord] = Net(source, sinks)

    rig_nets = list(itervalues(nets))  # Just the nets

    # Determine how many bits to use in the keys
    xyp_fields = BitField(32)
    xyp_fields.add_field("x", length=8, start_at=24)
    xyp_fields.add_field("y", length=8, start_at=16)
    xyp_fields.add_field("p", length=5, start_at=11)

    xyzp_fields = BitField(32)
    xyzp_fields.add_field("x", length=8, start_at=24)
    xyzp_fields.add_field("y", length=8, start_at=16)
    xyzp_fields.add_field("z", length=8, start_at=8)
    xyzp_fields.add_field("p", length=5, start_at=3)

    hilbert_fields = BitField(32)
    hilbert_fields.add_field("index", length=16, start_at=16)
    hilbert_fields.add_field("p", length=5, start_at=11)

    random.seed(321)
    rnd_fields = BitField(32)
    rnd_fields.add_field("rnd", length=12, start_at=20)
    rnd_seen = set()

    # Generate the routing keys
    net_keys_xyp = OrderedDict()
    net_keys_xyzp = OrderedDict()
    net_keys_hilbert = OrderedDict()
    net_keys_rnd = OrderedDict()
    for i, (x, y) in enumerate(chip for chip in hilbert_chip_order(machine) if
                               chip in machine):
        # Add the key for each net from each processor
        for p in range(1, 18):
            # Get the net
            net = nets[(x, y, p)]

            # Construct the xyp key/mask
            net_keys_xyp[net] = xyp_fields(x=x, y=y, p=p)

            # Construct the xyzp mask
            x_, y_, z_ = minimise_xyz(to_xyz((x, y)))
            net_keys_xyzp[net] = xyzp_fields(x=x_, y=y_, z=abs(z_), p=p)

            # Construct the Hilbert key/mask
            net_keys_hilbert[net] = hilbert_fields(index=i, p=p)

            # Construct the random 12 bit value field
            val = None
            while val is None or val in rnd_seen:
                val = random.getrandbits(12)
            rnd_seen.add(val)
            net_keys_rnd[net] = rnd_fields(rnd=val)

    # Route the network and then generate the routing tables
    constraints = list()
    print("Routing...")
    routing_tree = route(vertices_resources, rig_nets, machine, constraints,
                         placements, allocations)

    # Write the routing tables to file
    for fields, desc in ((net_keys_xyp, "xyp"),
                         (net_keys_xyzp, "xyzp"),
                         (net_keys_hilbert, "hilbert"),
                         (net_keys_rnd, "rnd")):
        print("Getting keys and masks...")
        keys = {net: (bf.get_value(), bf.get_mask()) for net, bf in
                iteritems(fields)}

        print("Constructing routing tables for {}...".format(desc))
        tables = routing_tree_to_tables(routing_tree, keys)
        print([len(x) for x in itervalues(tables)])

        print("Writing to file...")
        fn = "uncompressed/gaussian_{}_{}_{}.bin".format(
            machine.width, machine.height, desc)
        with open(fn, "wb+") as f:
            dump_routing_tables(f, tables)
Exemple #6
0
from matplotlib import pyplot as plt
import numpy as np
import random
from rig.geometry import to_xyz, minimise_xyz, shortest_torus_path_length
import seaborn as sns

random.seed(2801)

sns.set(context="paper", style="whitegrid", font="Times New Roman")

fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(3.5, 1))

# Compute the probability for the Gaussian model
g_prob = np.zeros((12, 12))

home = minimise_xyz(to_xyz((1, 6)))

for x in range(12):
    for y in range(12):
        target = minimise_xyz(to_xyz((x, y)))
        d = shortest_torus_path_length(home, target, 12, 12)
        g_prob[y, x] = d

g_prob = .5 * np.exp(-.65 * g_prob)

ax0.set_title("Locally-connected")
ax0.grid(False)
ax0.set_xticklabels([])
ax0.set_yticklabels([])
ax0.matshow(g_prob, vmin=0.0, vmax=1.0, origin='lower')
def get_network(machine, rng):
    # Compute the distance between chips
    dists = np.zeros((machine.width, machine.height, 17), dtype=np.uint32)

    for x, y in machine:
        dists[x, y, :] = shortest_torus_path_length(
            (0, 0, 0), minimise_xyz(to_xyz([x, y])),
            machine.width, machine.height
        )

    # Compute the probability of a target for each distance
    probs = 0.475**(dists + 1)
    centroid_probs = 0.25**(dists + 1)

    # Create the vertices for each core (and allocations and placements)
    vertices = OrderedDict()
    placements = OrderedDict()
    allocations = OrderedDict()
    resources = defaultdict(lambda: {Cores: 1})

    for x, y in machine:
        for p in range(17):
            # Create the new vertex for this core
            vx = common.Vertex(x, y, p)

            # Place and allocate
            vertices[x, y, p] = vx
            placements[vx] = (x, y)
            allocations[vx] = {Cores: slice(p, p+1)}

    # Keep track of targets which are the result of centroid(s)
    centroid_sinks = defaultdict(lambda: set())

    # Now construct the nets
    nets = list()
    for x, y, p in ((i, j, k) for k in range(17) for i, j in machine):
        # Get the source
        source = vertices[x, y, p]

        # Get the (local) sinks
        sinks = get_targets(x, y, probs, machine.width, machine.height,
                            rng, vertices)

        # Add centroid links if we have any (we have a 5% chance of connecting
        # to 1 centroid)
        if rng.uniform(0, 1) < 0.05:
            # Get the target co-ordinates
            c_sinks = get_targets(x, y, centroid_probs, machine.width,
                                  machine.height, rng, vertices)

            # Mark these as sinks relating to a centroid
            centroid_sinks[x, y, p].update(c_sinks)

            # Add to the general list of sinks
            sinks += c_sinks

        # Add the net
        nets.append(Net(source, sinks))

    # Route the nets
    logger.info("Routing...")

    # Get the centroid routes
    centroid_routes = route(resources, nets, machine, list(),
                            placements, allocations)

    # Prune back to get the local-only connections
    logger.info("Pruning...")
    local_routes = {
        net: common.get_pruned_routing_tree(tree, centroid_sinks[net.source])
        for net, tree in iteritems(centroid_routes)
    }

    return centroid_routes, local_routes
Exemple #8
0
from matplotlib import pyplot as plt
import numpy as np
import random
from rig.geometry import to_xyz, minimise_xyz, shortest_torus_path_length
import seaborn as sns

random.seed(2801)

sns.set(context="paper", style="whitegrid", font="Times New Roman")

fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(3.5, 1))

# Compute the probability for the Gaussian model
g_prob = np.zeros((12, 12))

home = minimise_xyz(to_xyz((1, 6)))

for x in range(12):
    for y in range(12):
        target = minimise_xyz(to_xyz((x, y)))
        d = shortest_torus_path_length(home, target, 12, 12)
        g_prob[y, x] = d

g_prob = .5 * np.exp(-.65*g_prob)

ax0.set_title("Locally-connected")
ax0.grid(False)
ax0.set_xticklabels([])
ax0.set_yticklabels([])
ax0.matshow(g_prob, vmin=0.0, vmax=1.0, origin='lower')
Exemple #9
0
def get_network(machine, rng):
    # Compute the distance between chips
    dists = np.zeros((machine.width, machine.height, 17), dtype=np.uint32)

    for x, y in machine:
        dists[x,
              y, :] = shortest_torus_path_length((0, 0, 0),
                                                 minimise_xyz(to_xyz([x, y])),
                                                 machine.width, machine.height)

    # Compute the probability of a target for each distance
    probs = 0.475**(dists + 1)
    centroid_probs = 0.25**(dists + 1)

    # Create the vertices for each core (and allocations and placements)
    vertices = OrderedDict()
    placements = OrderedDict()
    allocations = OrderedDict()
    resources = defaultdict(lambda: {Cores: 1})

    for x, y in machine:
        for p in range(17):
            # Create the new vertex for this core
            vx = common.Vertex(x, y, p)

            # Place and allocate
            vertices[x, y, p] = vx
            placements[vx] = (x, y)
            allocations[vx] = {Cores: slice(p, p + 1)}

    # Keep track of targets which are the result of centroid(s)
    centroid_sinks = defaultdict(lambda: set())

    # Now construct the nets
    nets = list()
    for x, y, p in ((i, j, k) for k in range(17) for i, j in machine):
        # Get the source
        source = vertices[x, y, p]

        # Get the (local) sinks
        sinks = get_targets(x, y, probs, machine.width, machine.height, rng,
                            vertices)

        # Add centroid links if we have any (we have a 5% chance of connecting
        # to 1 centroid)
        if rng.uniform(0, 1) < 0.05:
            # Get the target co-ordinates
            c_sinks = get_targets(x, y, centroid_probs, machine.width,
                                  machine.height, rng, vertices)

            # Mark these as sinks relating to a centroid
            centroid_sinks[x, y, p].update(c_sinks)

            # Add to the general list of sinks
            sinks += c_sinks

        # Add the net
        nets.append(Net(source, sinks))

    # Route the nets
    logger.info("Routing...")

    # Get the centroid routes
    centroid_routes = route(resources, nets, machine, list(), placements,
                            allocations)

    # Prune back to get the local-only connections
    logger.info("Pruning...")
    local_routes = {
        net: common.get_pruned_routing_tree(tree, centroid_sinks[net.source])
        for net, tree in iteritems(centroid_routes)
    }

    return centroid_routes, local_routes