Skip to content

Commit

Permalink
Created new Group._set_with_code_conditional will be needed for
Browse files Browse the repository at this point in the history
standalone mode, works in runtime but not used automatically, doesn't
work in standalone because _array_i is not defined
  • Loading branch information
thesamovar committed Sep 25, 2013
1 parent 00cc1d4 commit c5af402
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 12 deletions.
8 changes: 6 additions & 2 deletions brian2/codegen/codeobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ def create_codeobject(owner, name, abstract_code, namespace, variables, template
namespace = prepare_namespace(namespace, variables,
codeobj_class=codeobj_class)

logger.debug(name + " abstract code:\n" + abstract_code)
if isinstance(abstract_code, dict):
for k, v in abstract_code.items():
logger.debug('%s abstract code key %s:\n%s' % (name, k, v))
else:
logger.debug(name + " abstract code:\n" + abstract_code)
iterate_all = template.iterate_all
if isinstance(abstract_code, dict):
snippet = {}
Expand All @@ -76,7 +80,7 @@ def create_codeobject(owner, name, abstract_code, namespace, variables, template
variable_indices=variable_indices,
iterate_all=iterate_all)
snippet[ac_name] = snip
for k, v in snip_kwds:
for k, v in snip_kwds.items():
kwds[ac_name+'_'+k] = v

else:
Expand Down
2 changes: 1 addition & 1 deletion brian2/codegen/languages/cpp_lang.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def translate_statement_sequence(self, statements, variables, namespace,
func_namespace = func.implementations[codeobj_class].namespace
if func_namespace is not None:
namespace.update(func_namespace)

return (stripped_deindented_lines(code),
{'pointers_lines': stripped_deindented_lines(pointers),
'support_code_lines': stripped_deindented_lines(support_code),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Phase 1: we compute the indices where the conditional setting is to
# be applied, and to do this we want to vectorise over all the values,
# but we don't want to do the iterate all protocol, so we explicitly
# set the idx to be slice(None)
_vectorisation_idx = _idx = slice(None)
{% for line in code_lines['condition'] %}
{{line}}
{% endfor %}

# Phase 2: having computed _cond, the boolean array of points where
# the setting is to be applied, we want to vectorise over idx being
# only these values.
_vectorisation_idx = _idx = _cond
{% for line in code_lines['statement'] %}
{{line}}
{% endfor %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{% import 'common_macros.cpp' as common with context %}

{% macro main() %}
{{ common.insert_lines_commented('SUPPORT CODE', condition_support_code_lines) }}
{{ common.insert_lines('HANDLE DENORMALS', condition_denormals_code_lines) }}
{{ common.insert_lines('HASH DEFINES', condition_hashdefine_lines) }}
{{ common.insert_lines('POINTERS', condition_pointers_lines) }}
//// MAIN CODE ////////////
for(int _idx=0; _idx<_num_idx; _idx++)
{
const int _vectorisation_idx = _idx;
{{ common.insert_lines('CONDITION', code_lines['condition']) }}
if(_cond) {
{{ common.insert_lines('STATEMENT', code_lines['statement']) }}
}
}
{% endmacro %}

{% macro support_code() %}
{{ common.insert_lines('SUPPORT CODE', condition_support_code_lines) }}
{% endmacro %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
////////////////////////////////////////////////////////////////////////////
//// MAIN CODE /////////////////////////////////////////////////////////////

{% macro cpp_file() %}

#include "{{codeobj_name}}.h"
#include<math.h>
#include "brianlib/common_math.h"
#include<stdint.h>

////// SUPPORT CODE ///////
namespace {
{% for line in condition_support_code_lines %}
{{line}}
{% endfor %}
}

////// HASH DEFINES ///////
{% for line in condition_hashdefine_lines %}
{{line}}
{% endfor %}

void _run_{{codeobj_name}}(double t)
{
///// CONSTANTS ///////////
%CONSTANTS%
///// POINTERS ////////////
{% for line in condition_pointers_lines %}
{{line}}
{% endfor %}

//// MAIN CODE ////////////
const int _num_group_idx = _num_idx;
for(int _idx_group_idx=0; _idx_group_idx<_num_group_idx; _idx_group_idx++)
{
//const int _idx = _group_idx[_idx_group_idx];
const int _idx = _idx_group_idx;
const int _vectorisation_idx = _idx;
{% for line in code_lines['condition'] %}
{{line}}
{% endfor %}
if(_cond)
{
{% for line in code_lines['statement'] %}
{{line}}
{% endfor %}
}
}
}
{% endmacro %}

////////////////////////////////////////////////////////////////////////////
//// HEADER FILE ///////////////////////////////////////////////////////////

{% macro h_file() %}
#ifndef _INCLUDED_{{codeobj_name}}
#define _INCLUDED_{{codeobj_name}}

#include "arrays.h"

void _run_{{codeobj_name}}(double t);

#endif
{% endmacro %}
55 changes: 49 additions & 6 deletions brian2/groups/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,27 @@ def _set_with_code(self, variable, group_indices, code,
additional_namespace=additional_namespace,
check_units=check_units)
codeobj()


def _set_with_code_conditional(self, variable, cond, code,
template, check_units=True, level=0):
abstract_code_cond = '_cond = '+cond
abstract_code = variable.name + ' = ' + code
namespace = get_local_namespace(level + 1)
additional_namespace = ('implicit-namespace', namespace)
additional_variables = self.item_mapping.variables
check_code_units(abstract_code_cond, self,
additional_variables=additional_variables,
additional_namespace=additional_namespace)
# TODO: Have an additional argument to avoid going through the index
# array for situations where iterate_all could be used
codeobj = create_runner_codeobj(self,
{'condition': abstract_code_cond, 'statement': abstract_code},
template,
additional_variables=additional_variables,
additional_namespace=additional_namespace,
check_units=check_units)
codeobj()


def check_code_units(code, group, additional_variables=None,
additional_namespace=None,
Expand Down Expand Up @@ -249,6 +269,11 @@ def check_code_units(code, group, additional_variables=None,
DimensionMismatchError
If `code` has unit mismatches
'''
if isinstance(code, dict):
for v in code.values():
check_code_units(v, group, additional_variables=additional_variables,
additional_namespace=additional_namespace,
ignore_keyerrors=ignore_keyerrors)
all_variables = dict(group.variables)
if additional_variables is not None:
all_variables.update(additional_variables)
Expand All @@ -259,7 +284,13 @@ def check_code_units(code, group, additional_variables=None,
# Note that here we do not need to recursively descend into
# subexpressions. For unit checking, we only need to know the units of
# the subexpressions not what variables they refer to
_, _, unknown = analyse_identifiers(code, all_variables)
if isinstance(code, dict):
unknown = set()
for v in code.values():
_, _, u = analyse_identifiers(v, all_variables)
unknown |= u
else:
_, _, unknown = analyse_identifiers(code, all_variables)
try:
resolved_namespace = group.namespace.resolve_all(unknown,
additional_namespace,
Expand All @@ -272,7 +303,11 @@ def check_code_units(code, group, additional_variables=None,
else:
raise ex

check_units_statements(code, resolved_namespace, all_variables)
if isinstance(code, dict):
for v in code.values():
check_units_statements(v, resolved_namespace, all_variables)
else:
check_units_statements(code, resolved_namespace, all_variables)


def create_runner_codeobj(group, code, template_name, indices=None,
Expand Down Expand Up @@ -332,10 +367,18 @@ def create_runner_codeobj(group, code, template_name, indices=None,
all_variables = dict(group.variables)
if additional_variables is not None:
all_variables.update(additional_variables)

# Determine the identifiers that were used
_, used_known, unknown = analyse_identifiers(code, all_variables,
recursive=True)
if isinstance(code, dict):
used_known = set()
unknown = set()
for v in code.values():
_, uk, u = analyse_identifiers(v, all_variables, recursive=True)
used_known |= uk
unknown |= u
else:
_, used_known, unknown = analyse_identifiers(code, all_variables,
recursive=True)

logger.debug('Unknown identifiers in the abstract code: ' + str(unknown))

Expand Down
18 changes: 15 additions & 3 deletions dev/ideas/devices/cpp_standalone.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@
from brian2 import *
import time

BrianLogger.log_level_debug()

start = time.time()

if standalone_mode:
from brian2.devices.cpp_standalone import *
set_device('cpp_standalone')
else:
brian_prefs['codegen.target'] = 'weave'
#brian_prefs['codegen.target'] = 'numpy'

##### Define the model
tau = 1*ms
Expand All @@ -34,12 +39,19 @@
refractory=refractory,
name='gp')
M = SpikeMonitor(G)
#G2 = NeuronGroup(1, eqs, reset=reset, threshold=threshold, refractory=refractory, name='gp2')
G2 = NeuronGroup(1, eqs, reset=reset, threshold=threshold, refractory=refractory, name='gp2')
#S = Synapses(G, G2, 'w:volt', pre='V+=w')
# Run the network for 0 seconds to generate the code
G.V = '1*volt'
#print G.V.__class__
#exit()
#G.V['i>10'] = '1*volt'
#G._set_with_code_conditional(G.variables['V'], 'i>10', '1*volt', 'group_variable_set_conditional')
#print G.V[0], G.V[11]
#exit()
net = Network(G,
M,
#G2,
G2,
#S,
)

if not standalone_mode:
Expand Down

0 comments on commit c5af402

Please sign in to comment.