You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs_sphinx/user/computation.rst
+52-6Lines changed: 52 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -143,12 +143,7 @@ something like this may not behave as you would like::
143
143
144
144
The current C++ standalone code generation only works for a fixed number of `~Network.run` statements, not with loops.
145
145
If you need to do loops or other features not supported automatically, you can do so by inspecting the generated
146
-
C++ source code and modifying it, or by inserting code directly into the main loop as follows::
147
-
148
-
device.insert_code('main', '''
149
-
cout << "Testing direct insertion of code." << endl;
150
-
''')
151
-
146
+
C++ source code and modifying it, or by inserting code directly into the main loop as described below.
152
147
153
148
Variables
154
149
~~~~~~~~~
@@ -177,6 +172,57 @@ of the number of threads. However, this is working fine for networks with not
177
172
too small timestep (dt > 0.1ms), and results do not depend on the number of
178
173
threads used in the simulation.
179
174
175
+
Custom code injection
176
+
~~~~~~~~~~~~~~~~~~~~~
177
+
It is possible to insert custom code directly into the generated code of a
178
+
standalone simulation using a Device's `~.Device.insert_code` method::
179
+
180
+
device.insert_code(slot, code)
181
+
182
+
``slot`` can be one of ``main``, ``before_start``, ``after_start``,
183
+
``before_network_run``, ``after_network_run``, ``before_end`` and ``after_end``,
184
+
which determines where the code is inserted. ``code`` is the code in the
185
+
Device's language. Here is an example for the C++ Standalone Device::
186
+
187
+
device.insert_code('main', '''
188
+
cout << "Testing direct insertion of code." << endl;
189
+
''')
190
+
191
+
For the C++ Standalone Device, all code is inserted into the ``main.cpp`` file,
192
+
here into the ``main`` slot, referring to the main simulation function.
193
+
This is a simplified version of this function in ``main.cpp``::
194
+
195
+
int main(int argc, char **argv)
196
+
{
197
+
// before_start
198
+
brian_start();
199
+
// after_start
200
+
201
+
{{main_lines}}
202
+
203
+
// before_end
204
+
brian_end();
205
+
// after_end
206
+
207
+
return 0;
208
+
}
209
+
210
+
``{{main_lines}}`` is replaced in the generated code with the actual simulation.
211
+
Code inserted into the ``main`` slot will be placed within the
212
+
``{{main_lines}}``. ``brian_start`` allocates and initializes all arrays needed
213
+
during the simulation and ``brian_end`` writes the results to disc and
214
+
deallocates memory. Within the ``{{main_lines}}``, all ``Network`` objects
215
+
defined in Python are created and run. Code inserted in the
216
+
``before/after_network_run`` slot will be inserted around the ``Network.run``
217
+
call, which starts the time loop. Note that if your Python script has multiple
218
+
``Network`` objects or multiple ``run`` calls, code in the
219
+
``before/after_network_run`` slot will be inserted around each ``Network.run``
220
+
call in the generated code.
221
+
222
+
The code injection mechanism has been used for benchmarking experiments, see
223
+
e.g. `here for Brian2CUDA benchmarks <https://github.com/brian-team/brian2cuda/blob/835c978ad758bc0621e34344c1fb7b811ef8a118/brian2cuda/tests/features/cuda_configuration.py#L148-L156>`_ or `here for Brian2GeNN benchmarks <https://github.com/brian-team/brian2genn_benchmarks/blob/6d1a6d9d97c05653cec2e413c9fd312cfe13e15c/benchmark_utils.py#L78-L136>`_.
0 commit comments