Compiling and Simulating Networks

SNS-Toolbox is designed with two goals: designing networks with a simple scripting system, and simulating these networks in an efficient manner. In Building Networks we covered the different options available when designing a network, here we will walk through the backend interface and how to simulate SNS networks using SNS-Toolbox.

General Interface and Process

When simulating a network, we start with a Network object:

net = Network('Name of network')

This network object is not capable of being simulated in its current state, it is just a container containing a description of the various components within a network. In order to simulate this network, we need to compile it to a simulation backend:

model = net.compile(dt=0.01, backend='numpy', device='cpu', debug=False)

where dt is the simulation timestep in ms, backend takes a string representing any of the backends included within SNS-Toolbox, device is the hardware the network will run on ('cpu' for the processor, 'cuda' for the GPU), and debug causes various debugging information to be printed to the console if set to true.

Simulating a Network

Now that a model is built, the model can be called timestep by timestep to simulate the network dynamics as follows:

for i in range(num_steps):
    data = model(x)

where x is a vector of external inputs which is applied at each step. If there are no external inputs present in the network, it can be run as:

for i in range(num_steps):
    data = model()

Backend Statistics

All of the simulation backends within SNS-Toolbox implement the same neural dynamics, just using different software strategies. Detailed descriptions of each backend option are presented in the following sections, for performance on a certain network topology please see the following performance chart:

_images/backend_comparison.png

Based on experimentation, here are some general recommendations for networks with a roughly 1:1 comparison between the number of neurons and synapses:

  • for small networks (under ~300), SNS_Numpy and SNS_Torch (CPU version) will execute the fastest.

  • Networks with 300-7000 neurons will execute the fastest using SNS_Torch and a CUDA-compatible GPU.

  • Networks with 7000-11000 neurons will execute the fastest using SNS_Sparse and a CUDA-compatible GPU.

  • For networks with over 11000 neurons, due to memory constraints the simple iterative SNS_Manual backend is the best option.

Additionally, due to constraints with memory access and architecture, each of these backends has a maximum possible network size before the host system runs out of memory. These examples are given below:

If you run a simulation and find conflicting empirical performance data, please email the project maintainer and our documentation may be updated.

SNS_Numpy

SNS_Numpy simulates networks using the numpy python package. All parameters are stored in np.ndarray objects. Build this backend with the following command:

model = net.compile(backend='numpy')

Note that SNS_Numpy only supports execution on the CPU.

SNS_Torch

SNS_Torch simulates using PyTorch. All parameters are stored in torch.Tensor objects. SNS_Torch networks can be simulated on either the CPU or a CUDA-enabled GPU. To simulate on the CPU, build the network as

model = net.compile(backend='torch', device='cpu')

For GPU simulation, use

model = net.compile(backend='torch', device='cuda')

or for machines with multiple GPUs

model = SNS_Torch(net, device='cuda:i')

where i is the index of the desired GPU.

SNS_Sparse

SNS_Sparse simulates using PyTorch Sparse. All parameters are specified as torch.Tensor objects, then stored in torch.sparse_coo_tensor objects. SNS_Sparse networks can be simulated on either the CPU or a CUDA-enabled GPU. To simulate on the CPU, build the network as

model = net.compile(backend='sparse', device='cpu')

For GPU simulation, use

model = net.compile(backend='sparse', device='cuda')

or for machines with multiple GPUs

model = net.compile(backend='sparse', device='cuda:i')

where i is the index of the desired GPU.

Due to the process of building sparse tensors and matrices, SNS_Sparse networks take longer to compile than the other backends. For improved performance, loading of a pre-built network may improve performance. See Saving and Loading Networks for more information.

SNS_Iterative

NOTE: This backend will not be updated to incorporate any neural or synaptic models added after version 1.5.0. As such, it is not recommended for new models.

The SNS_Iterative backend implements the same neural dynamics as the other backends, but does so using iterative operations instead of vectors and matrices. Its primary purpose is as a benchmarking comparison for the vector-based algorithms, however can be useful for extremely large and sparse networks which exceed the memory constraints of other backends.

All parameters are stored in np.ndarray objects. This backend can be built with the following command:

model = net.compile(backend='iterative')

Note that SNS_Iterative only supports execution on the CPU.