Code generation

The latest SVN version of Brian includes a new experimental package, brian.experimental.codegen, which is designed for automatic generation of code for numerical integration in Python, C++ and GPU C++. If the global preference usecodegen is True then it will be used automatically for all nonlinear differential equations. If usecodegenweave is True then C code will be generated, otherwise Python code. In all cases the code runs faster. GPU code is not currently used. Use the file to activate it for all your code. As an example of how it works, let's use the following Brian Equations object:

[python] eqs = Equations(''' dV/dt = -WV/(10second) : volt dW/dt = -V*2/(1second) : volt ''') [/python]

The codegen module generates the following code for the Euler update scheme. For Python:

[python] V = _S[0] W = _S[1] V__tmp = -0.1VW W__tmp = -1.0V2 V += V__tmpdt W += W__tmp*dt [/python]

For C:

[cpp] double V__Sbase = _S+0num_neurons; double W__Sbase = _S+1num_neurons; for(int _i=0;_i<num_neurons;_i++){ double &V = V__Sbase++; double &W = W__Sbase++; double V__tmp = -0.1VW; double W__tmp = -1.0pow(V, 2); V += V__tmpdt; W += W__tmp*dt; } [/cpp]

And for the GPU:

[cpp] global void stateupdate(int num_neurons, double t, double S) { int i = blockIdx.x * blockDim.x + threadIdx.x; if(i>=num_neurons) return; double &V = S[i+0num_neurons]; double &W = S[i+1num_neurons]; double &V = V__Sbase++; double &W = W__Sbase++; double V__tmp = -0.1VW; double W__tmp = -1.0pow(V, 2); V += V__tmpdt; W += W__tmpdt; } [/cpp]

These are all generated from the following template for the Euler integration scheme:

[python] euler_scheme = [ (('foreachvar', 'nonzero'), ''' $vartype ${var}__tmp = $var_expr '''), (('foreachvar', 'nonzero'), ''' $var += ${var}__tmp*dt ''') ] [/python]

The other schemes are the RK2 and exponential Euler scheme. For example, the exponential Euler scheme is:

[python] exp_euler_scheme = [ (('foreachvar', 'nonzero'), ''' $vartype ${var}__B = @substitute(var_expr, {var:0}) $vartype ${var}__A = @substitute(var_expr, {var:1}) ${var}__A -= ${var}__B ${var}__B /= ${var}__A ${var}__A = dt '''), (('foreachvar', 'nonzero'), ''' $var += ${var}__B $var = exp(${var}__A) $var -= ${var}__B ''') ] [/python]

On the Equations above, this generates the following Python code:

[python] V = _S[0] W = _S[1] V__B = 0 W__B = -1.0V2 V__A = -0.1W W__A = -1.0V2 V__A -= V__B W__A -= W__B V__B /= V__A W__B /= W__A V__A = dt W__A = dt V += V__B W += W__B V = exp(V__A) W *= exp(W__A) V -= V__B W -= W__B [/python]

And similarly for C++ and GPU.

We will be extending the automatic generation of code into other areas, including resets, thresholds, and STDP code.

If you have any comments on the approach, bug reports, etc. please let us know!