Using brian2cuda and cpp_stardalone for a brian2 script with loop of runs

I’m trying to use brian2cuda and cpp_standalone to run the STDP example at:

The only thing I changed is to add a loop to the runs

  for i in range(2):
      run(100*second, report='text')

The run will crash in the 2nd iteration as expected .
So in cpp_standalone mode, I modified the “main.cpp” as the follows and it runs fine.

  for(int i = 0; i<2; i++) {
      std::cout<<"i: "<<i<<std::endl;, report_progress, 10.0);

when using brian2cuda, same modification on will leads to the following errors when running the 2nd iteration:

    98.989 s (98%) simulated in 1m 10s, estimated 1s remaining.
    100.000 s (100%) simulated in 1m 10s
    i: 1
    Starting simulation at t=100.000 s for duration 100.000 s
    ERROR: cudaMemcpy( &_num_events, &_eventspace[_num_spikespace - 1], sizeof(int32_t), cudaMemcpyDeviceToHost ) failed at code_objects/ : an illegal memory access was encountered
    terminate called after throwing an instance of 'thrust::system::system_error'
      what():  device free failed: driver shutting down

Is there a way to allow brian2cuda to run in a loop? The reason for question is that I’m looping over a large sample of stimuli and run, e.g. 100*ms, for each stimulus.

Hi. Both cpp_standalone and cuda_standalone support multiple runs without editing the generated code, by using set_device with build_on_run=False and an explicit call: Computational methods and efficiency — Brian 2 2.5.1 documentation

That said, this will be quite inefficient if you do it for many runs, due to a number of duplicated code files that have to be compiled. How are you changing the stimuli between the runs, actually? In most cases, there is no need to use multiple runs to deal with multiple stimuli, you can usually have a single run and switch stimuli via a TimedArray or a run_regularly statement: Input stimuli — Brian 2 2.5.1 documentation

When going through a loop of samples, I need to rerun a sample with different condition, e.g. stimulus rate, until the condition is satisfied before moving to the next sample. This is what we discussed in this thread:

Re-run the model in a previous time segment during a long run

I used runtime mode since then. Now trying to use brian2cuda, I might have to make changes directly in the cuda source. Further inputs would be appreciated.

One other option would be to use this slightly hacky approach here (the second, “sequential” script):

You do a run, check the results, change some parameter of the model, and then run the model again, without recompiling anything. This means that each run starts again from 0s, but that might not be a problem for you? You can keep, e.g., synaptic weights if you use the same mechanism to initialize them, and then set them for each run with the previous run’s values.

Thanks Marcel, I will give it a try

Hi Marcel

One quick question to make sure I use the function correctly:

 input = PoissonGroup(N, rates=0*Hz)
 F = initialize_parameter(input.rates, 15*Hz)
 print('1----: ', input.rates)

Will the PoissonGroup run with 0Hz or 15Hz. The printout after “initialize_parameter” still print 0Hz instead of 15Hz. After executing run() command, the print out is 15*Hz. Did I do it correctly?

Hi @DavidKing2020 . Yes, this is correct, it will use 15Hz. The initialize_parameter/set_parameter_value function directly set the values in the generated C++ code which is only executed when you call run. Before that, the code on the Python side does not know what the value will be. The solution in my gist is a bit hacky, there would be ways to make this work in a more intuitive way.
However, I am not 100% sure whether it will correctly broadcast the scalar value to an array here. To be on the safe side, try to always set the array with the size of the group, e.g. here you’d use initialize_parameter(input.rates, np.ones(N)*15*Hz).

1 Like