Brian2GeNN: multiple synaptic output variables not supported

I attempted this but I get the same error as above (that it cannot find -lcuda)
Did I do it correctly (I did it a couple times by accident :sweat_smile:)?

(brianenv) [Nina@utwks62681 bin]$ echo $PATH
/home/Nina/.conda/envs/brianenv/bin:/usr/condabin:/usr/local/cuda-7.5/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/puttenmjam/.local/bin:/home/puttenmjam/bin:/opt/scripts:/var/lib/snapd/snap/bin:/Nina/Downloads/genn-4.3.3/bin:/home/Nina/Downloads/genn-4.3.3/bin:/usr/local/cuda-7.5/lib64:/usr/local/cuda-7.5/lib64:/usr/local/cuda-7.5/lib64

The /usr/local/cuda-7.5/lib64 path needs to be added to the LD_LIBRARY_PATH variable (or most likely you do not have any LD_LIBRARY_PATH variable at the moment, so you can set it to this value instead of adding it to it). In your output, you seem to have added it to PATH instead.

After making much progress in building my own model in brian2, I would like to get back to this. After playing around with different delays and synaptic weights, I found that it is not necessary to make these heterogeneous. I would really like to speed up my simulation, so; If all synapses are the same (same equations and same parameters (delays and weights and stuff)), but I have a sparse connectivity (I have some connection matrix), is it possible to restructure the model to make simulations much faster like you mentioned here? It should be possible to use some type of matrix multiplication right?

Hi again. The “extreme” solution would indeed be to do a calculation of the synaptic propagation yourself, but this would either mean to write a network_operation (rather straight-forward, but you could no longer use C++ standalone more or Brian2GeNN) or a function implementation in C++ (considerably less straightforward). But there is one technique that is very general and should help considerably: move computation from the synapses into the (pre-synaptic) neuron. Except for extremely sparse connectivity, you will have an order of magnitude more synapses than neurons. So every computation that is done “per synapse” and “per timestep” is very costly, and should be avoided if possible. Let’s have a look at some equations (more or less copied from your earlier posts):

eqs_synapsmodel = '''
s_nmda_tot_post = w *u_f * x_d * s_nmda :1 (summed)
ds_nmda/dt = -s_nmda/(taus_nmda)+alpha_nmda*x*(1-s_nmda) : 1 (clock-driven)
dx/dt = -x/(taux_nmda) :1 (clock-driven)
dx_d/dt = (1-x_d)/tau_d :1 (clock-driven)
du_f/dt = (U-u_f)/tau_f :1 (clock-driven)
w : 1
'''

eqs_onpre = '''
x += 1
u_f += U*(1-u_f)
x_d *= (1-u_f)
'''

These equations are solved for every synapse individually, but you can see that since tau_d etc. are constants, almost all of these equations will only depend on the pre-synaptic neuron, i.e. they will have exactly the same value for all synapses that are coming from the same neuron. Simulating them individually is therefore quite a waste of resources. In the above equations this means that you can move x, x_d, u_f, and s_nmda to the equations of the pre-synaptic neuron. The related statements in on_pre would go into the reset of the pre-synaptic neuron. The summed variable has to stay in the Synapses and then needs to refer to x_pre, etc. Now, there is one complication: all this only works if there are no synaptic delays, since a neuron’s reset statement will update the variables immediately. There is a workaround to this limitation, at least if all synapses coming from the same neuron have the same delay: you can introduce a “fake synapse” from each neuron onto itself, which triggers the update instead of using the reset statement. This way, you can set a delay on this synapse to have it trigger the modifications with a delay.
Finally, it might make sense to have a look at the output of profiling_summary first (note that using the name argument for objects will make this output more readable), to make sure you are not optimizing in the wrong place.