Beispiel #1
0
 def translate_expression(self, expr):
     for varname, var in self.variables.iteritems():
         if isinstance(var, Function):
             impl_name = var.implementations[self.codeobj_class].name
             if impl_name is not None:
                 expr = word_substitute(expr, {varname: impl_name})
     return CPPNodeRenderer().render_expr(expr).strip()
Beispiel #2
0
def freeze(code, ns):
    # this is a bit of a hack, it should be passed to the template somehow
    for k, v in ns.items():

        if (isinstance(v, Variable) and not isinstance(v, AttributeVariable) and
              v.scalar and v.constant and v.read_only):
            v = v.get_value()

        if isinstance(v, basestring):
            code = word_substitute(code, {k: v})
        elif isinstance(v, numbers.Number):
            # Use a renderer to correctly transform constants such as True or inf
            renderer = CPPNodeRenderer()
            string_value = renderer.render_expr(repr(v))
            if v < 0:
                string_value = '(%s)' % string_value
            code = word_substitute(code, {k: string_value})
        else:
            pass  # don't deal with this object
    return code
Beispiel #3
0
def freeze(code, ns):
    # this is a bit of a hack, it should be passed to the template somehow
    for k, v in ns.items():

        if (isinstance(v, Variable) and not isinstance(v, AttributeVariable)
                and v.scalar and v.constant and v.read_only):
            v = v.get_value()

        if isinstance(v, basestring):
            code = word_substitute(code, {k: v})
        elif isinstance(v, numbers.Number):
            # Use a renderer to correctly transform constants such as True or inf
            renderer = CPPNodeRenderer()
            string_value = renderer.render_expr(repr(v))
            if v < 0:
                string_value = '(%s)' % string_value
            code = word_substitute(code, {k: string_value})
        else:
            pass  # don't deal with this object
    return code
Beispiel #4
0
 def translate_expression(self, expr):
     for varname, var in self.variables.iteritems():
         if isinstance(var, Function):
             try:
                 impl_name = var.implementations[self.codeobj_class].name
             except KeyError:
                 raise NotImplementedError('Function {} is not available '
                                           'for use with '
                                           'GeNN.'.format(var.name))
             if impl_name is not None:
                 expr = word_substitute(expr, {varname: impl_name})
     return CPPNodeRenderer().render_expr(expr).strip()
Beispiel #5
0
 def fill_with_array(self, var, arr):
     arr = np.asarray(arr)
     array_name = self.get_array_name(var, access_data=False)
     arr = np.asarray(arr)
     if arr.shape == ():
         if var.size == 1:
             value = CPPNodeRenderer().render_expr(repr(arr.item(0)))
             # For a single assignment, generate a code line instead of storing the array
             self.main_queue.append(
                 ('set_by_single_value', (array_name, 0, value)))
         else:
             self.main_queue.append(
                 ('set_by_constant', (array_name, arr.item())))
     else:
         # Using the std::vector instead of a pointer to the underlying
         # data for dynamic arrays is fast enough here and it saves us some
         # additional work to set up the pointer
         static_array_name = self.static_array(array_name, arr)
         self.main_queue.append(
             ('set_by_array', (array_name, static_array_name)))
Beispiel #6
0
 def translate_expression(self, expr):
     expr = word_substitute(expr, self.func_name_replacements)
     return CPPNodeRenderer().render_expr(expr).strip()
Beispiel #7
0
def test_parse_expressions_cpp():
    if prefs.codegen.target != 'weave':
        pytest.skip('weave-only test')
    parse_expressions(CPPNodeRenderer(), cpp_evaluator)
Beispiel #8
0
def test_parse_expressions_cpp():
    parse_expressions(CPPNodeRenderer(), cpp_evaluator)
    def generate_main_source(self, writer):
        main_lines = []
        procedures = [('', main_lines)]
        runfuncs = {}
        for func, args in self.main_queue:
            if func=='run_code_object':
                codeobj, = args
                main_lines.append('_run_%s();' % codeobj.name)
            elif func=='run_network':
                net, netcode = args
                main_lines.extend(netcode)
            elif func=='set_by_constant':
                arrayname, value, is_dynamic = args
                size_str = arrayname+'.size()' if is_dynamic else '_num_'+arrayname
                code = '''
                {pragma}
                for(int i=0; i<{size_str}; i++)
                {{
                    {arrayname}[i] = {value};
                }}
                '''.format(arrayname=arrayname, size_str=size_str,
                           value=CPPNodeRenderer().render_expr(repr(value)),
                           pragma=openmp_pragma('static'))
                main_lines.extend(code.split('\n'))
            elif func=='set_by_array':
                arrayname, staticarrayname, is_dynamic = args
                size_str = arrayname+'.size()' if is_dynamic else '_num_'+arrayname
                code = '''
                {pragma}
                for(int i=0; i<{size_str}; i++)
                {{
                    {arrayname}[i] = {staticarrayname}[i];
                }}
                '''.format(arrayname=arrayname, size_str=size_str,
                           staticarrayname=staticarrayname,
                           pragma=openmp_pragma('static'))
                main_lines.extend(code.split('\n'))
            elif func=='set_by_single_value':
                arrayname, item, value = args
                code = '{arrayname}[{item}] = {value};'.format(arrayname=arrayname,
                                                               item=item,
                                                               value=value)
                main_lines.extend([code])
            elif func=='set_array_by_array':
                arrayname, staticarrayname_index, staticarrayname_value = args
                code = '''
                {pragma}
                for(int i=0; i<_num_{staticarrayname_index}; i++)
                {{
                    {arrayname}[{staticarrayname_index}[i]] = {staticarrayname_value}[i];
                }}
                '''.format(arrayname=arrayname, staticarrayname_index=staticarrayname_index,
                           staticarrayname_value=staticarrayname_value, pragma=openmp_pragma('static'))
                main_lines.extend(code.split('\n'))
            elif func=='resize_array':
                array_name, new_size = args
                main_lines.append("{array_name}.resize({new_size});".format(array_name=array_name,
                                                                            new_size=new_size))
            elif func=='insert_code':
                main_lines.append(args)
            elif func=='start_run_func':
                name, include_in_parent = args
                if include_in_parent:
                    main_lines.append('%s();' % name)
                main_lines = []
                procedures.append((name, main_lines))
            elif func=='end_run_func':
                name, include_in_parent = args
                name, main_lines = procedures.pop(-1)
                runfuncs[name] = main_lines
                name, main_lines = procedures[-1]
            elif func=='seed':
                seed = args
                nb_threads = prefs.devices.cpp_standalone.openmp_threads
                if nb_threads == 0:  # no OpenMP
                    nb_threads = 1
                main_lines.append('for (int _i=0; _i<{nb_threads}; _i++)'.format(nb_threads=nb_threads))
                if seed is None:  # random
                    main_lines.append('    rk_randomseed(brian::_mersenne_twister_states[_i]);')
                else:
                    main_lines.append('    rk_seed({seed!r}L + _i, brian::_mersenne_twister_states[_i]);'.format(seed=seed))
            else:
                raise NotImplementedError("Unknown main queue function type "+func)

        self.runfuncs = runfuncs

        # generate the finalisations
        for codeobj in self.code_objects.itervalues():
            if hasattr(codeobj.code, 'main_finalise'):
                main_lines.append(codeobj.code.main_finalise)

        # The code_objects are passed in the right order to run them because they were
        # sorted by the Network object. To support multiple clocks we'll need to be
        # smarter about that.
        main_tmp = self.code_object_class().templater.main(None, None,
                                                           main_lines=main_lines,
                                                           code_objects=self.code_objects.values(),
                                                           report_func=self.report_func,
                                                           dt=float(self.defaultclock.dt),
                                                           user_headers=self.headers
                                                           )
        writer.write('main.cpp', main_tmp)
Beispiel #10
0
    def generate_main_source(self, writer):
        main_lines = []
        procedures = [('', main_lines)]
        runfuncs = {}
        for func, args in self.main_queue:
            if func == 'run_code_object':
                codeobj, = args
                main_lines.append('_run_%s();' % codeobj.name)
            elif func == 'run_network':
                net, netcode = args
                main_lines.extend(netcode)
            elif func == 'set_by_constant':
                arrayname, value = args
                code = '''
                {pragma}
                for(int i=0; i<_num_{arrayname}; i++)
                {{
                    {arrayname}[i] = {value};
                }}
                '''.format(arrayname=arrayname,
                           value=CPPNodeRenderer().render_expr(repr(value)),
                           pragma=openmp_pragma('static'))
                main_lines.extend(code.split('\n'))
            elif func == 'set_by_array':
                arrayname, staticarrayname = args
                code = '''
                {pragma}
                for(int i=0; i<_num_{staticarrayname}; i++)
                {{
                    {arrayname}[i] = {staticarrayname}[i];
                }}
                '''.format(arrayname=arrayname,
                           staticarrayname=staticarrayname,
                           pragma=openmp_pragma('static'))
                main_lines.extend(code.split('\n'))
            elif func == 'set_by_single_value':
                arrayname, item, value = args
                code = '{arrayname}[{item}] = {value};'.format(
                    arrayname=arrayname, item=item, value=value)
                main_lines.extend([code])
            elif func == 'set_array_by_array':
                arrayname, staticarrayname_index, staticarrayname_value = args
                code = '''
                {pragma}
                for(int i=0; i<_num_{staticarrayname_index}; i++)
                {{
                    {arrayname}[{staticarrayname_index}[i]] = {staticarrayname_value}[i];
                }}
                '''.format(arrayname=arrayname,
                           staticarrayname_index=staticarrayname_index,
                           staticarrayname_value=staticarrayname_value,
                           pragma=openmp_pragma('static'))
                main_lines.extend(code.split('\n'))
            elif func == 'resize_array':
                array_name, new_size = args
                main_lines.append("{array_name}.resize({new_size});".format(
                    array_name=array_name, new_size=new_size))
            elif func == 'insert_code':
                main_lines.append(args)
            elif func == 'start_run_func':
                name, include_in_parent = args
                if include_in_parent:
                    main_lines.append('%s();' % name)
                main_lines = []
                procedures.append((name, main_lines))
            elif func == 'end_run_func':
                name, include_in_parent = args
                name, main_lines = procedures.pop(-1)
                runfuncs[name] = main_lines
                name, main_lines = procedures[-1]
            else:
                raise NotImplementedError("Unknown main queue function type " +
                                          func)

        self.runfuncs = runfuncs

        # generate the finalisations
        for codeobj in self.code_objects.itervalues():
            if hasattr(codeobj.code, 'main_finalise'):
                main_lines.append(codeobj.code.main_finalise)

                # The code_objects are passed in the right order to run them because they were
        # sorted by the Network object. To support multiple clocks we'll need to be
        # smarter about that.
        main_tmp = CPPStandaloneCodeObject.templater.main(
            None,
            None,
            main_lines=main_lines,
            code_objects=self.code_objects.values(),
            report_func=self.report_func,
            dt=float(defaultclock.dt),
            user_headers=prefs['codegen.cpp.headers'])
        writer.write('main.cpp', main_tmp)
Beispiel #11
0
    def variableview_set_with_index_array(self, variableview, item, value,
                                          check_units):
        if isinstance(item, slice) and item == slice(None):
            item = 'True'
        value = Quantity(value)

        if (isinstance(item, int) or
            (isinstance(item, np.ndarray)
             and item.shape == ())) and value.size == 1:
            array_name = self.get_array_name(variableview.variable,
                                             access_data=False)
            value = CPPNodeRenderer().render_expr(
                repr(np.asarray(value).item(0)))
            # For a single assignment, generate a code line instead of storing the array
            self.main_queue.append(
                ('set_by_single_value', (array_name, item, value)))

        elif (value.size == 1 and item == 'True'
              and variableview.index_var_name == '_idx'):
            # set the whole array to a scalar value
            if have_same_dimensions(value, 1):
                # Avoid a representation as "Quantity(...)" or "array(...)"
                value = float(value)
            variableview.set_with_expression_conditional(
                cond=item, code=repr(value), check_units=check_units)
        # Simple case where we don't have to do any indexing
        elif (item == 'True' and variableview.index_var == '_idx'):
            self.fill_with_array(variableview.variable, value)
        else:
            # We have to calculate indices. This will not work for synaptic
            # variables
            try:
                indices = np.asarray(
                    variableview.indexing(item,
                                          index_var=variableview.index_var))
            except NotImplementedError:
                raise NotImplementedError(
                    ('Cannot set variable "%s" this way in '
                     'standalone, try using string '
                     'expressions.') % variableview.name)
            # Using the std::vector instead of a pointer to the underlying
            # data for dynamic arrays is fast enough here and it saves us some
            # additional work to set up the pointer
            arrayname = self.get_array_name(variableview.variable,
                                            access_data=False)
            if indices.shape == ():
                self.main_queue.append(
                    ('set_by_single_value', (arrayname, indices.item(),
                                             float(value))))
            else:
                staticarrayname_index = self.static_array(
                    '_index_' + arrayname, indices)
                staticarrayname_value = self.static_array(
                    '_value_' + arrayname, value)
                self.main_queue.append(
                    ('set_array_by_array', (arrayname, staticarrayname_index,
                                            staticarrayname_value)))
            staticarrayname_index = self.static_array('_index_' + arrayname,
                                                      indices)
            if (indices.shape != () and
                (value.shape == () or (value.size == 1 and indices.size > 1))):
                value = np.repeat(value, indices.size)
            staticarrayname_value = self.static_array('_value_' + arrayname,
                                                      value)
            self.main_queue.append(
                ('set_array_by_array', (arrayname, staticarrayname_index,
                                        staticarrayname_value)))
Beispiel #12
0
    def generate_main_source(self, writer, main_includes):
        main_lines = []
        procedures = [('', main_lines)]
        runfuncs = {}
        for func, args in self.main_queue:
            if func == 'run_code_object':
                codeobj, = args
                codeobj.runs_every_tick = False
                main_lines.append('_run_%s();' % codeobj.name)
            elif func == 'run_network':
                net, netcode = args
                for clock in net._clocks:
                    line = "{net.name}.add(&{clock.name}, _sync_clocks);".format(
                        clock=clock, net=net)
                    netcode.insert(1, line)
                main_lines.extend(netcode)
            elif func == 'set_by_constant':
                arrayname, value, is_dynamic = args
                size_str = arrayname + ".size()" if is_dynamic else "_num_" + arrayname
                code = '''
                for(int i=0; i<{size_str}; i++)
                {{
                    {arrayname}[i] = {value};
                }}
                '''.format(arrayname=arrayname,
                           size_str=size_str,
                           value=CPPNodeRenderer().render_expr(repr(value)))
                main_lines.extend(code.split('\n'))
                pointer_arrayname = "dev{arrayname}".format(
                    arrayname=arrayname)
                if arrayname.endswith('space'):  # eventspace
                    pointer_arrayname += '[current_idx{arrayname}]'.format(
                        arrayname=arrayname)
                if is_dynamic:
                    pointer_arrayname = "thrust::raw_pointer_cast(&dev{arrayname}[0])".format(
                        arrayname=arrayname)
                line = "cudaMemcpy({pointer_arrayname}, &{arrayname}[0], sizeof({arrayname}[0])*{size_str}, cudaMemcpyHostToDevice);".format(
                    arrayname=arrayname,
                    size_str=size_str,
                    pointer_arrayname=pointer_arrayname,
                    value=CPPNodeRenderer().render_expr(repr(value)))
                main_lines.extend([line])
            elif func == 'set_by_single_value':
                arrayname, item, value = args
                pointer_arrayname = "dev{arrayname}".format(
                    arrayname=arrayname)
                if arrayname in self.dynamic_arrays.values():
                    pointer_arrayname = "thrust::raw_pointer_cast(&dev{arrayname}[0])".format(
                        arrayname=arrayname)
                code = '''
                {arrayname}[{item}] = {value};
                cudaMemcpy(&{pointer_arrayname}[{item}], &{arrayname}[{item}], sizeof({arrayname}[0]), cudaMemcpyHostToDevice);
                '''.format(pointer_arrayname=pointer_arrayname,
                           arrayname=arrayname,
                           item=item,
                           value=value)
                main_lines.extend([code])
            elif func == 'set_by_array':
                arrayname, staticarrayname, is_dynamic = args
                size = "_num_" + arrayname
                if is_dynamic:
                    size = arrayname + ".size()"
                code = '''
                for(int i=0; i<_num_{staticarrayname}; i++)
                {{
                    {arrayname}[i] = {staticarrayname}[i];
                }}
                '''.format(arrayname=arrayname,
                           staticarrayname=staticarrayname,
                           size_str=size)
                pointer_arrayname = "dev{arrayname}".format(
                    arrayname=arrayname)
                if arrayname in self.dynamic_arrays.values():
                    pointer_arrayname = "thrust::raw_pointer_cast(&dev{arrayname}[0])".format(
                        arrayname=arrayname)
                main_lines.extend(code.split('\n'))
                line = '''
                cudaMemcpy({pointer_arrayname}, &{arrayname}[0], sizeof({arrayname}[0])*{size_str}, cudaMemcpyHostToDevice);
                '''.format(pointer_arrayname=pointer_arrayname,
                           staticarrayname=staticarrayname,
                           size_str=size,
                           arrayname=arrayname)
                main_lines.extend([line])
            elif func == 'set_array_by_array':
                arrayname, staticarrayname_index, staticarrayname_value = args
                code = '''
                for(int i=0; i<_num_{staticarrayname_index}; i++)
                {{
                    {arrayname}[{staticarrayname_index}[i]] = {staticarrayname_value}[i];
                }}
                cudaMemcpy(dev{arrayname}, &{arrayname}[0], sizeof({arrayname}[0])*_num_{arrayname}, cudaMemcpyHostToDevice);
                '''.format(arrayname=arrayname,
                           staticarrayname_index=staticarrayname_index,
                           staticarrayname_value=staticarrayname_value)
                main_lines.extend(code.split('\n'))
            elif func == 'resize_array':
                array_name, new_size = args
                main_lines.append('''
                    {array_name}.resize({new_size});
                    dev{array_name}.resize({new_size});
                '''.format(array_name=array_name, new_size=new_size))
            elif func == 'insert_code':
                main_lines.append(args)
            elif func == 'start_run_func':
                name, include_in_parent = args
                if include_in_parent:
                    main_lines.append('%s();' % name)
                main_lines = []
                procedures.append((name, main_lines))
            elif func == 'end_run_func':
                name, include_in_parent = args
                name, main_lines = procedures.pop(-1)
                runfuncs[name] = main_lines
                name, main_lines = procedures[-1]
            elif func == 'seed':
                seed = args
                if seed is not None:
                    main_lines.append(
                        'curandSetPseudoRandomGeneratorSeed(random_float_generator, {seed!r}ULL);'
                        .format(seed=seed))
                    # generator offset needs to be reset to its default (=0)
                    main_lines.append(
                        'curandSetGeneratorOffset(random_float_generator, 0ULL);'
                    )
                # else a random seed is set in objects.cu::_init_arrays()
            else:
                raise NotImplementedError("Unknown main queue function type " +
                                          func)

        # generate the finalisations
        for codeobj in self.code_objects.itervalues():
            if hasattr(codeobj.code, 'main_finalise'):
                main_lines.append(codeobj.code.main_finalise)

        main_tmp = CUDAStandaloneCodeObject.templater.main(
            None,
            None,
            main_lines=main_lines,
            code_objects=self.code_objects.values(),
            report_func=self.report_func,
            dt=float(defaultclock.dt),
            additional_headers=main_includes)
        writer.write('main.cu', main_tmp)
Beispiel #13
0
 def translate_expression(self, expr):
     return CPPNodeRenderer().render_expr(expr).strip()