return '-fopenmp' elif pragma_type == 'sections': return '#pragma omp sections' elif pragma_type == 'section': return '#pragma omp section' else: raise ValueError('Unknown OpenMP pragma "%s"' % pragma_type) class CPPStandaloneCodeObject(CodeObject): ''' C++ standalone code object The ``code`` should be a `~brian2.codegen.templates.MultiTemplate` object with two macros defined, ``main`` (for the main loop code) and ``support_code`` for any support code (e.g. function definitions). ''' templater = Templater('brian2.devices.cpp_standalone', '.cpp', env_globals={'c_data_type': c_data_type, 'openmp_pragma': openmp_pragma, 'constant_or_scalar': constant_or_scalar}) generator_class = CPPCodeGenerator def __call__(self, **kwds): return self.run() def run(self): get_device().main_queue.append(('run_code_object', (self,))) codegen_targets.add(CPPStandaloneCodeObject)
self.before_after_blocks.append(block) class CUDAStandaloneAtomicsCodeObject(CUDAStandaloneCodeObject): ''' CUDA standalone code object which uses atomic operations for parallel execution The ``code`` should be a `~brian2.codegen.templates.MultiTemplate` object with two macros defined, ``main`` (for the main loop code) and ``support_code`` for any support code (e.g. function definitions). ''' generator_class = CUDAAtomicsCodeGenerator codegen_targets.add(CUDAStandaloneCodeObject) codegen_targets.add(CUDAStandaloneAtomicsCodeObject) rand_code = ''' #define _rand(vectorisation_idx) (_ptr_array_%CODEOBJ_NAME%_rand[vectorisation_idx]) ''' rand_impls = DEFAULT_FUNCTIONS['rand'].implementations rand_impls.add_implementation(CUDAStandaloneCodeObject, code=rand_code, name='_rand') randn_code = ''' #define _randn(vectorisation_idx) (_ptr_array_%CODEOBJ_NAME%_randn[vectorisation_idx]) ''' randn_impls = DEFAULT_FUNCTIONS['randn'].implementations randn_impls.add_implementation(CUDAStandaloneCodeObject,
def compile_block(self, block): pass # Compilation will be handled in device def run_block(self, block): if block == 'run': get_device().main_queue.append((f"{block}_code_object", (self,))) else: # Check the C++ code whether there is anything to run cpp_code = getattr(self.code, f"{block}_cpp_file") if len(cpp_code) and 'EMPTY_CODE_BLOCK' not in cpp_code: get_device().main_queue.append((f"{block}_code_object", (self,))) self.before_after_blocks.append(block) codegen_targets.add(CPPStandaloneCodeObject) # At module initialization time, we do not yet know whether the code will be # run with OpenMP or not. We therefore use a "dynamic implementation" which # generates the rand/randn implementation during code generation. def generate_rand_code(rand_func, owner): nb_threads = prefs.devices.cpp_standalone.openmp_threads if nb_threads == 0: # no OpenMP thread_number = '0' else: thread_number = 'omp_get_thread_num()' if rand_func == 'rand': rk_call = 'rk_double' elif rand_func == 'randn': rk_call = 'rk_gauss'
from brian2.codegen.codeobject import CodeObject from brian2.codegen.targets import codegen_targets from brian2.codegen.templates import Templater from .genn_generator import * __all__ = ['GeNNCodeObject', 'GeNNUserCodeObject'] class GeNNCodeObject(CodeObject): ''' Class of code objects that generate GeNN "code snippets" ''' templater = Templater('brian2genn', '.cpp', env_globals={'c_data_type': c_data_type, 'openmp_pragma': openmp_pragma, 'constant_or_scalar': constant_or_scalar}) generator_class = GeNNCodeGenerator class GeNNUserCodeObject(CPPStandaloneCodeObject): ''' Class of code objects that generate GeNN "user code" ''' templater = CPPStandaloneCodeObject.templater.derive('brian2genn') #, env_globals={'c_data_type': c_data_type, # 'openmp_pragma': openmp_pragma, # 'constant_or_scalar': constant_or_scalar}) generator_class = CPPCodeGenerator codegen_targets.add(GeNNCodeObject) codegen_targets.add(GeNNUserCodeObject)
from brian2.codegen.targets import codegen_targets from brian2.codegen.templates import Templater from .genn_generator import * __all__ = ['GeNNCodeObject', 'GeNNUserCodeObject'] class GeNNCodeObject(CodeObject): ''' Class of code objects that generate GeNN "code snippets" ''' templater = Templater('brian2genn', '.cpp', env_globals={'c_data_type': c_data_type, 'openmp_pragma': openmp_pragma, 'constant_or_scalar': constant_or_scalar, 'zip': zip}) generator_class = GeNNCodeGenerator class GeNNUserCodeObject(CPPStandaloneCodeObject): ''' Class of code objects that generate GeNN "user code" ''' templater = CPPStandaloneCodeObject.templater.derive('brian2genn') #, env_globals={'c_data_type': c_data_type, # 'openmp_pragma': openmp_pragma, # 'constant_or_scalar': constant_or_scalar}) generator_class = CPPCodeGenerator codegen_targets.add(GeNNCodeObject) codegen_targets.add(GeNNUserCodeObject)
''' ''' from brian2.devices.cpp_standalone.codeobject import CPPStandaloneCodeObject from brian2.codegen.generators.cpp_generator import CPPCodeGenerator from brian2.codegen.targets import codegen_targets __all__ = [] class SampleDeviceCodeObject(CPPStandaloneCodeObject): ''' Very minimalist CodeObject builds on CPPStandaloneCodeObject and changes one template ''' # Derive the templater from the CPPStandaloneCodeObject templater. We change # just one file, main.cpp in the brian2sampledevice/templates directory, to add # some output. templater = CPPStandaloneCodeObject.templater.derive('brian2sampledevice') generator_class = CPPCodeGenerator # Register this code object class codegen_targets.add(SampleDeviceCodeObject)