Parameter space exploration, nengo_ocl and SpiNNaker

Hi @nikhilgarg,

Because NengoOCL uses OpenCL to run Nengo models on the GPU, each object (or class) that you use in your model has to have a corresponding implementation in OpenCL (i.e., C) code. The NengoOCL codebase contains all of this (OpenCL) code for the objects found in Nengo core. Thus, if you want to use a custom object (e.g., your custom neuron class), you’ll have to implement the OpenCL code for your custom class and get NengoOCL to use that while it is building your Nengo model.

I demonstrated how to insert custom OCL code for NengoOCL models here, but I’ll also summarize it below.

In NengoOCL, when a Nengo model is built, every object that is used in the Nengo model is built using a _plan_<operator_name> function. For example, if you have LIF neurons in your model, NengoOCL will attempt to call the sim._plan_LIF() function to build those neurons. If you look in the NengoOCL simulator code, you’ll see that such a function has been defined. For your custom neuron class, NengoOCL will be looking to call a sim._plan_MyLIF_in() function, which isn’t defined, and this is what causes the error.

The _plan_<operator_name> function only sets up the arrays that will be used to transfer data to and from the GPU. In each _plan_<operator_name> function, it returns a call to another function that actually contains the OpenCL code. Using the example of the _plan_LIF() function, it returns an instance of the plan_lif() function (the name plan_lif here is just to maintain consistency… you can name it anything you want really), which is defined here. In the plan_lif function, you will see the strings decs and text which are the C definitions for the object declarations and neuron logic code respectively.

Thus, to implement and use your custom neuron object in your Nengo model in NengoOCL, you’ll need to:

  1. Create a plan_mylif_in function that implements your custom neuron class in OCL code. You can use the plan_lif function as a reference. You can probably use that code verbatim, just remove the adaptive lif and fast life code, and change this line.
  2. Subclass the NengoOCL simulator, and within that subclass, create a _plan_MyLIF_in function that calls your plan_mylif_in function (that you created in Step 1). The NengoOCL simulator subclass should look like this:
import nengo_ocl
class CustomOCLSimulator(nengo_ocl.Simulator):
    def _plan_MyLIF_in(self, ops):
        ...
        <code for _plan_MyLIF_in>
        ...
  1. You can use the code for the existing _plan_LIF method as a reference for your custom _plan_MyLIF_in method. Since you only changed the neuron logic, and not the input signals, it should be identical, actually.
  2. When you create your NengoOCL simulator and run it, use your CustomOCLSimulator instead of the default nengo_ocl.Simulator, like so:
with nengo.Network() as model:
    ...
    <define nengo model>
    ...

with CustomOCLSimulator(model, context=ocl_context) as sim:
    sim.run(1)

And that should be it! :smiley:

As I mentioned above, please also read this forum post to get an actual working example of the steps I have described above. In that post, I uploaded example code (bcm_mask_ocl.py – contains the custom OCL code, and custom Simulator class; test_bcm_mask_ocl.py – contains the Nengo model code and the simulator runs) that you can reference as well.

1 Like