Frequently asked questions

How do I add a new kernel?

When you make a new Nengo neuron type or learning rule, it’s unlikely that NengoOCL will know how to simulate it. To teach NengoOCL how to simulate it, you have to write an OpenCL kernel.

A good starting point for this is to look at the existing kernels in nengo_ocl/clra_nonlinearities.py and study one that is similar to the kernel you wish to add. For each kernel, you’ll see that there are a lot of arguments that go in. Essentially, they’re all lists of different aspects of the input ragged arrays. When we’re doing computations with ragged arrays, essentially we want to write kernels that can take in a list of arrays of different sizes, and perform the operation on each one of those arrays.

Let’s take the BCM kernel as an example. It gets arguments shape0s and shape1s; these are lists of the .shape[0] and .shape[1] for each output. Then we have pre_stride0s and pre_starts; these give the strides along axis 0 and a pointer to where the data starts for each array in the pre ragged array. pre_data is the buffer itself. Then we have similar things for the post ragged array, followed by theta and delta. Finally, there’s a list of the alphas (learning rates) for all the different operators. So each of these lists will be of length N, where N is the number of SimBCM operators that we’ve combined into this single kernel.

Then there’s the kernel itself. It starts by getting ids, as is typical with OpenCL kernels. Here, k is the index of which array we’re treating right now (0 <= k < N), so we use it to index into all of the input lists. ij tells the kernel which individual element to treat. We split it into i and j (row and column indices), and then this kernel computes element (i, j) of the output (delta).