Brian2cuda parameter initialization

Description of problem

I am trying to simulate a mixed analog-digital neuromorphic environment with brian2cuda (everything works flawlessly with just brian2), so I need to have noisy initialization of parameters. Problem is, with brian2cuda certain parameters seem to have the possibility to be initialized only with scalars (I would avoid to create a for loop for every neurongroups, it would kill the efficiency of standalone code generation)

Minimal code to reproduce problem

I am using custom neural and synaptic model so I won’t attach the full model. Please note that the initialization of weight does not give any issues, which appear when I try to initialize the C_syn_exc2 parameter.

from brian2 import *
import brian2cuda
set_device('cuda_standalone', directory='my_folder', compile=True)
n_class = 50
inh_len = n_class*9*90
s_ei_C = np.random.normal(loc=1, scale=0.2, size=inh_len)* 1.5
s_ei = chip.add_connection (L1,L_inh,synapse_type='AMPA')
s_ei.connect (True)
s_ei.weight = np.random.normal(loc=1, scale=0.2, size=inh_len)*30
s_ei.C_syn_exc2 = 's_ei_C*pF'

=========================
What you have aready tried

  1. initializing directly:
s_ei.C_syn_exc2= np.random.normal(loc=1, scale=0.2, size=inh_len)* 1.5
  1. initialize a dictionary and passing the key:
s_ei_C = np.random.normal(loc=1, scale=0.2, size=inh_len)* 1.5
params = {'s_ei_C':s_ei_C            
    }
s_ei.C_syn_exc2 = params['s_ei_C']
  1. initializing without the string format:

s_ei.C_syn_exc2 = s_ei_C*pF

====================
Actual output (if relevant)

KeyError: ‘Variable s_ei_C was found in the namespace, but is not a scalar value’

==================
Full traceback of error (if relevant)


Cell In[1], line 158
    s_ei.C_syn_exc2 = 's_ei_C*pF'

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/groups/group.py:424 in __setattr__
    var.get_addressable_value_with_unit(name, self).set_item(slice(None),

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/core/variables.py:876 in set_item
    self.set_with_expression_conditional(item, value,

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/core/base.py:278 in device_override_decorated_function
    return func(*args, **kwds)

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/core/variables.py:1033 in set_with_expression_conditional
    codeobj = create_runner_codeobj(self.group,

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/codegen/codeobject.py:355 in create_runner_codeobj
    variables = group.resolve_all(identifiers | set(needed_variables) | set(template_variables),

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/groups/group.py:737 in resolve_all
    resolved[identifier] = self._resolve(identifier,

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/groups/group.py:697 in _resolve
    return self._resolve_external(identifier, run_namespace=run_namespace)

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/groups/group.py:903 in _resolve_external
    raise KeyError('Variable %s was found in the namespace, but is'

KeyError: 'Variable s_ei_C was found in the namespace, but is not a scalar value'

========================

Thenk you very much in advance for the help

Hi @lparr. Unfortunately, the documentation is a bit lacking in this regard, but constants/variables that are referred to in strings need to be either model variables (i.e. defined in the equations of a NeuronGroup/Synapses, etc.), or scalar values defined as a variable in the namespace (alternatively, explicitly handed over via the namespace argument). This is the reason for the error in this code

s_ei.C_syn_exc2 = 's_ei_C*pF'

As the error message states, it found an external constant of the name s_ei_C, but this is an array, and not a scalar value as expected.
However, everything else you listed (i.e. your options 1–3) should work. Are you sure the code does not fail for other reasons when you use them? If you are sure the parameter initialization is the problem, please give the error message for one of these cases.

Hi @mstimberg thanks for the answer!

I should precise that in option 2 I also add the " *pF" as you can see now from the editing I made to the post.

To respond to your question yes, I am 100% sure that the code does not fail for other reasons because, as I stated at the beginning of the post, both training, testing, and plotting phases went just smoothly with brian2. Now I need to scale up my simulation so I started to try brian2cuda.

Anyway, following your suggestion I tried again with option 2 (initializing with a dictionary), I also made sure that both the key in the dict and the variable have different names with the following code:

s_ei_c = np.random.normal(loc=1, scale=0.2, size=inh_len)* 1.5*pF
params = {‘s_ei_C’:s_ei_c}
s_ei.C_syn_exc2 = params[‘s_ei_C’]

Full traceback:

Traceback (most recent call last):

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/devices/cpp_standalone/device.py:446 in variableview_set_with_index_array
    indices = np.asarray(variableview.indexing(item,

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/synapses/synapses.py:532 in __call__
    start, stop, step = index.indices(len(self.synaptic_pre.get_value()))

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/core/variables.py:464 in get_value
    return self.device.get_value(self)

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/devices/cpp_standalone/device.py:513 in get_value
    raise NotImplementedError('Cannot retrieve the values of state '

NotImplementedError: Cannot retrieve the values of state variables in standalone code before the simulation has been run.


During handling of the above exception, another exception occurred:

Traceback (most recent call last):

  Cell In[1], line 157
    s_ei.C_syn_exc2 = params['s_ei_C']

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/groups/group.py:424 in __setattr__
    var.get_addressable_value_with_unit(name, self).set_item(slice(None),

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/core/variables.py:898 in set_item
    self.set_with_index_array(slice(None), value,

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/core/base.py:276 in device_override_decorated_function
    return getattr(curdev, name)(*args, **kwds)

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2cuda/device.py:1711 in variableview_set_with_index_array
    super().variableview_set_with_index_array(variableview, *args, **kwargs)

  File ~/anaconda3/envs/CUDA/lib/python3.10/site-packages/brian2/devices/cpp_standalone/device.py:449 in variableview_set_with_index_array
    raise NotImplementedError(('Cannot set variable "%s" this way in '

NotImplementedError: Cannot set variable "C_syn_exc2" this way in standalone, try using string expressions.

As you can see the error is different from before. If you have any other suggestions I’m all ears!

Hi @Iparr. Thanks for the additional information, as I expected this is quite different from the “not a scalar” issue – in particular, it would not work if you looped, either. I was a bit confused by your initial post mentioning neuron groups, but the issue that you have is specific to synapses: The problem is that in standalone mode (including cuda_standalone), synapses are not generated until the simulation is run. When you assign a vector of values to a synaptic variable, Brian tries to check that the size of that vector is correct, but it cannot do this in standalone mode (since the synapses haven’t been created, yet, and e.g. for probabilistic connections, we cannot know how many there will be). More recent versions of Brian 2 handle this a bit better for situations where the number of synapses is actually fixed, and regardless of this there are hacky workarounds if you are sure that the number of synapses is fixed.

But long story short, there is a much easier solution in your case, you can directly use Brian’s internal machinery to generate the random numbers instead of creating them in Python and pushing them into the variable:

s_ei.C_syn_exc2 = '(1 + randn()*0.2)*1.5*pF'

This will work, since it creates the random values only when the simulation runs, in the final generated C++/CUDA code. The expression does not have a hardcoded number of synapses in it, it will generate a random number for each synapse – it therefore does not has to know in advance how many synapses there are.

Hope that makes some sense!

Hi @mstimberg ,

Just great, this response solved all my issues! I am sorry if the first post was a little bit fuzzy…

I think that the main point which was not clear here was that parameter initialization should not be just string-based but should be string-based AND handled by the internal machinery of brian2.

Really thank you!

1 Like