Skip to content

Commit

Permalink
Fix profiling mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
mstimberg committed Jul 27, 2023
1 parent 7412c46 commit 8028d5d
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 53 deletions.
102 changes: 50 additions & 52 deletions brian2genn/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ def __init__(self):
'before_end': [],
'after_end': []}

#: Use GeNN's kernel timings?
self.kernel_timings = False

def insert_code(self, slot, code):
'''
Insert custom C++ code directly into ``main.cpp``. The available slots
Expand Down Expand Up @@ -407,14 +410,15 @@ def code_object(self, owner, name, abstract_code, variables, template_name,
# the run_regularly operation (will be directly called from
# engine.cpp)
codeobj = super().code_object(owner, name,
abstract_code,
variables,
'stateupdate',
variable_indices,
codeobj_class=CPPStandaloneCodeObject,
template_kwds=template_kwds,
override_conditional_write=override_conditional_write,
)
abstract_code,
variables,
'stateupdate',
variable_indices,
codeobj_class=CPPStandaloneCodeObject,
template_kwds=template_kwds,
override_conditional_write=override_conditional_write,
)

# FIXME: The following is redundant with what is done during
# the code object creation above. At the moment, the code
# object does not allow us to access the information we
Expand Down Expand Up @@ -464,13 +468,13 @@ def code_object(self, owner, name, abstract_code, variables, template_name,
elif template_name in ['reset', 'synapses', 'stateupdate', 'threshold']:
codeobj_class = GeNNCodeObject
codeobj = super().code_object(owner, name,
abstract_code,
variables,
template_name,
variable_indices,
codeobj_class=codeobj_class,
template_kwds=template_kwds,
override_conditional_write=override_conditional_write,
abstract_code,
variables,
template_name,
variable_indices,
codeobj_class=codeobj_class,
template_kwds=template_kwds,
override_conditional_write=override_conditional_write,
)
self.simple_code_objects[codeobj.name] = codeobj
else:
Expand All @@ -491,13 +495,13 @@ def code_object(self, owner, name, abstract_code, variables, template_name,
else:
mrl_template_name='max_row_length_array'
codeobj = super().code_object(owner, mrl_name,
abstract_code,
variables,
mrl_template_name,
variable_indices,
codeobj_class=codeobj_class,
template_kwds=template_kwds,
override_conditional_write=override_conditional_write,
abstract_code,
variables,
mrl_template_name,
variable_indices,
codeobj_class=codeobj_class,
template_kwds=template_kwds,
override_conditional_write=override_conditional_write,
)
#self.code_objects['%s_max_row_length' % owner.name] = codeobj
self.code_objects.pop(mrl_name, None) # remove this from the normal list of code objects
Expand All @@ -507,14 +511,14 @@ def code_object(self, owner, name, abstract_code, variables, template_name,
self.max_row_length_run_calls.append('_run_%s();' % mrl_name)

codeobj = super().code_object(owner, name,
abstract_code,
variables,
template_name,
variable_indices,
codeobj_class=codeobj_class,
template_kwds=template_kwds,
override_conditional_write=override_conditional_write,
)
abstract_code,
variables,
template_name,
variable_indices,
codeobj_class=codeobj_class,
template_kwds=template_kwds,
override_conditional_write=override_conditional_write,
)
# FIXME: is this actually necessary or is it already added by the super?
self.code_objects[codeobj.name] = codeobj
return codeobj
Expand Down Expand Up @@ -754,14 +758,7 @@ def build(self, directory='GeNNworkspace', compile=True, run=True,
logger.debug(
"Writing GeNN project to directory " + os.path.normpath(directory))

# FIXME: This is only needed to keep Brian2GeNN compatible with Brian2 2.0.1 and earlier
if isinstance(self.arange_arrays, dict):
arange_arrays = sorted([(var, start)
for var, start in
self.arange_arrays.items()],
key=lambda var_start: var_start[0].name)
else:
arange_arrays = self.arange_arrays
arange_arrays = self.arange_arrays

# write the static arrays
for code_object in self.code_objects.values():
Expand Down Expand Up @@ -1726,7 +1723,8 @@ def generate_model_source(self, writer, main_lines, use_GPU):
max_row_length_synapses=self.max_row_length_synapses,
codeobj_inc=codeobj_inc,
dtDef=self.dtDef,
profiled=self.enable_profiling,
profiled=self.kernel_timings,
prefs=prefs,
precision=precision,
header_files=prefs['codegen.cpp.headers']
)
Expand All @@ -1741,7 +1739,7 @@ def generate_main_source(self, writer, main_lines):
main_lines=main_lines,
header_files=header_files,
source_files=sorted(self.source_files),
profiled=self.enable_profiling,
profiled=self.kernel_timings,
)
writer.write('main.*', runner_tmp)

Expand Down Expand Up @@ -1875,19 +1873,17 @@ def copy_source_files(self, writer, directory):
self.header_files.add('b2glib/' + file)

def network_run(self, net, duration, report=None, report_period=10 * second,
namespace=None, profile=False, level=0, **kwds):
# We store this as an instance variable for later access
self.enable_profiling = profile

namespace=None, profile=None, level=0, **kwds):
self.kernel_timings = profile
# Allow setting `profile` in the `set_device` call (used e.g. in brian2cuda
# SpeedTest configurations)
if profile is None:
self.enable_profiling = self.build_options.get("profile", None)
self.kernel_timings = self.build_options.pop("profile", None)
# If not set, check the deprecated preference
if prefs.devices.genn.kernel_timing:
if profile is None and prefs.devices.genn.kernel_timing:
logger.warn("The preference 'devices.genn.kernel_timing' is "
"deprecated, please set profile=True instead")
self.enable_profiling = True
self.kernel_timings = True
if kwds:
logger.warn(('Unsupported keyword argument(s) provided for run: '
+ '%s') % ', '.join(kwds.keys()))
Expand All @@ -1914,16 +1910,18 @@ def network_run(self, net, duration, report=None, report_period=10 * second,
# Network.objects to avoid memory leaks
self.net_objects = _get_all_objects(self.net.objects)
super().network_run(net=net, duration=duration,
report=report,
report_period=report_period,
namespace=namespace,
level=level + 1)
report=report,
report_period=report_period,
namespace=namespace,
level=level + 1,
profile=False)

self.run_statement_used = True


def network_get_profiling_info(self, net):
fname = os.path.join(self.project_dir, 'test_output', 'test.time')
if not os.path.exists(fname):
if not self.kernel_timings:
raise ValueError("No profiling info collected (need to set "
"profile = True ?)")
net._profiling_info = []
Expand Down
3 changes: 2 additions & 1 deletion brian2genn/templates/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ int main(int argc, char *argv[])
string cmd= std::string("mkdir ") +OutDir;
system(cmd.c_str());
string name;
{% if profiled %}
name= OutDir+ "/"+ argv[1] + ".time";
FILE *timef= fopen(name.c_str(),"a");

{% endif %}
fprintf(stderr, "# DT %g \n", DT);
fprintf(stderr, "# totalTime %f \n", totalTime);

Expand Down

0 comments on commit 8028d5d

Please sign in to comment.