def get_header_preamble(lang): """ Returns a list of defines, macros, etc. to be included in all headers for a given languages Parameters ---------- lang: str The target language Returns ------- preamble: list of str The preamble to include """ utils.check_lang(lang) if lang == 'c': return [textwrap.dedent(""" #ifdef _OPENMP #include <omp.h> #else #warning 'OpenMP not found! Unexpected results may occur if using more than one \ thread.' #define omp_get_num_threads() (1) #define omp_get_thread_num() (0) #endif """.strip())] return []
def get_target(lang, device=None, compiler=None): """ Parameters ---------- lang : str One of the supported languages, {'c', 'cuda', 'opencl'} device : :class:`pyopencl.Device` If supplied, and lang is 'opencl', passed to the :class:`loopy.PyOpenCLTarget` compiler: str If supplied, the C-compiler to use Returns ------- The correct loopy target type """ utils.check_lang(lang) # set target if lang == 'opencl': return lp.PyOpenCLTarget(device=device) elif lang == 'c': return lp.ExecutableCTarget(compiler=compiler) elif lang == 'cuda': return lp.CudaTarget() elif lang == 'ispc': return lp.ISPCTarget()
def __init__(self, name, lang, mode='w', is_header=False, include_own_header=False, use_filter=True, try_indent=False): self.name = name self.mode = mode self.lang = lang utils.check_lang(lang) self.headers = [] self.std_headers = [] self.is_header = is_header self.include_own_header = include_own_header if self.is_header: self.headers = ['mechanism'] if not self.name.endswith( 'mechanism' + utils.header_ext[lang]) else [] self.std_headers = get_standard_headers(lang) self.filter = lambda x: x assert not self.include_own_header, 'Cannot include this file in itself' self.preamble = get_header_preamble(lang) else: self.filter = self.preamble_filter if not use_filter: self.filter = lambda x: x self.lines = [] self.defines = [] self.try_indent = try_indent
def get_header_preamble(lang): """ Returns a list of defines, macros, etc. to be included in all headers for a given languages Parameters ---------- lang: str The target language Returns ------- preamble: list of str The preamble to include """ utils.check_lang(lang) if lang == 'opencl': return [ textwrap.dedent(""" #if __OPENCL_C_VERSION__ < 120 #pragma OPENCL EXTENSION cl_khr_fp64: enable #endif """) ] return []
def get_standard_headers(lang): """ Returns a list of standard headers to include for a given target language Parameters ---------- lang : str The target language """ utils.check_lang(lang) if lang == 'opencl': return [] elif lang == 'cuda': return [] return []
def __init__(self, width=None, depth=None, ilp=False, unr=None, lang='opencl', order='C', rate_spec=RateSpecialization.fixed, rate_spec_kernels=False, rop_net_kernels=False, platform='', knl_type='map', auto_diff=False, use_atomics=True, use_private_memory=False, jac_type=JacobianType.exact, jac_format=JacobianFormat.full, seperate_kernels=True, device=None, device_type=None): self.width = width self.depth = depth if not utils.can_vectorize_lang[lang]: assert not (width or depth), ( "Can't use a vectorized form with unvectorizable language," " {}".format(lang)) assert not (width and depth), ( 'Cannot use deep and wide vectorizations simulataneously') self.ilp = ilp self.unr = unr utils.check_lang(lang) self.lang = lang assert order in ['C', 'F'], 'Order {} unrecognized'.format(order) self.order = order self.rate_spec = rate_spec self.rate_spec_kernels = rate_spec_kernels self.rop_net_kernels = rop_net_kernels self.platform = platform self.device_type = device_type self.device = device assert knl_type in ['mask', 'map'] self.knl_type = knl_type self.auto_diff = auto_diff self.use_atomics = use_atomics self.use_private_memory = use_private_memory self.jac_format = jac_format self.jac_type = jac_type self.seperate_kernels = seperate_kernels # need to find the first platform that has the device of the correct # type if self.lang == 'opencl' and self.platform and cl is not None: if not isinstance(self.platform, cl.Platform): self.device_type = cl.device_type.ALL check_name = None if platform.lower() == 'cpu': self.device_type = cl.device_type.CPU elif platform.lower() == 'gpu': self.device_type = cl.device_type.GPU elif platform.lower() == 'accelerator': self.device_type = cl.device_type.ACCELERATOR else: check_name = self.platform self.platform = None platforms = cl.get_platforms() for p in platforms: try: cl.Context(dev_type=self.device_type, properties=[(cl.context_properties.PLATFORM, p)]) if not check_name or check_name.lower() in p.get_info( cl.platform_info.NAME).lower(): self.platform = p break except cl.cffi_cl.RuntimeError: pass if not self.platform: raise MissingPlatformError(platform) if not isinstance(self.device, cl.Device) and \ self.device_type is not None: # finally a matching device self.device = self.platform.get_devices( device_type=self.device_type) if not self.device: raise MissingDeviceError(self.device_type, self.platform) self.device = self.device[0] self.device_type = self.device.get_info(cl.device_info.TYPE) # check for broken vectorizations self.raise_on_broken()
def __init__(self, width=None, depth=None, ilp=False, unr=None, lang='opencl', order='C', rate_spec=RateSpecialization.fixed, rate_spec_kernels=False, rop_net_kernels=False, platform='', kernel_type=KernelType.jacobian, auto_diff=False, use_atomic_doubles=True, use_atomic_ints=True, jac_type=JacobianType.exact, jac_format=JacobianFormat.full, device=None, device_type=None, is_simd=None, unique_pointers=False, explicit_simd=None): self.width = width self.depth = depth if not utils.can_vectorize_lang[lang]: assert not (width or depth), ( "Can't use a vectorized form with unvectorizable language," " {}".format(lang)) assert not (width and depth), ( 'Cannot use deep and wide vectorizations simulataneously') self.ilp = ilp self.unr = unr utils.check_lang(lang) self.lang = lang utils.check_order(order) self.order = order self.rate_spec = utils.to_enum(rate_spec, RateSpecialization) self.rate_spec_kernels = rate_spec_kernels self.rop_net_kernels = rop_net_kernels self.platform = platform self.device_type = device_type self.device = device self.auto_diff = auto_diff self.use_atomic_doubles = use_atomic_doubles self.use_atomic_ints = use_atomic_ints self.jac_format = utils.to_enum(jac_format, JacobianFormat) self.jac_type = utils.to_enum(jac_type, JacobianType) self._is_simd = is_simd self.explicit_simd = explicit_simd self.explicit_simd_warned = False if self.lang != 'opencl' and self.explicit_simd: logger = logging.getLogger(__name__) logger.warn( 'explicit-SIMD flag has no effect on non-OpenCL targets.') self.kernel_type = utils.to_enum(kernel_type, KernelType) self.unique_pointers = unique_pointers if self._is_simd or self.explicit_simd: assert width or depth, ( 'Cannot use explicit SIMD types without vectorization') # need to find the first platform that has the device of the correct # type if self.lang == 'opencl' and not self.platform_is_pyopencl \ and cl is not None: self.device_type = cl.device_type.ALL check_name = None if self.platform_name.lower() == 'cpu': self.device_type = cl.device_type.CPU elif self.platform_name.lower() == 'gpu': self.device_type = cl.device_type.GPU elif self.platform_name.lower() == 'accelerator': self.device_type = cl.device_type.ACCELERATOR else: check_name = self.platform self.platform = None platforms = cl.get_platforms() for p in platforms: try: cl.Context(dev_type=self.device_type, properties=[(cl.context_properties.PLATFORM, p) ]) if not check_name or check_name.lower() in p.get_info( cl.platform_info.NAME).lower(): self.platform = p break except cl.cffi_cl.RuntimeError: pass if not self.platform: raise MissingPlatformError(platform) if not isinstance(self.device, cl.Device) and (self.device_type is not None): # finally a matching device self.device = self.platform.get_devices( device_type=self.device_type) if not self.device: raise MissingDeviceError(self.device_type, self.platform) self.device = self.device[0] self.device_type = self.device.get_info(cl.device_info.TYPE) elif self.lang == 'opencl': self.device_type = 'CL_DEVICE_TYPE_ALL' # check for broken vectorizations self.raise_on_broken()
def pywrap(lang, source_dir, build_dir=None, out_dir=None, obj_dir=None, additional_outputs=[], ktype=KernelType.jacobian, **kwargs): """Generates a Python wrapper for the given language and source files Parameters ---------- lang : {'cuda', 'c', 'tchem'} Programming language of pyJac (cuda, c) or TChem source_dir : str Directory path of source files. build_dir : str Directory path of the generated c/cuda/opencl library out_dir : Optional [str] Directory path for the output python library obj_dir: Optional [str] Directory path to place the compiled objects additional_outputs : list of str If specified, these additional arguments should be considered outputs of the generated kernel call. Useful in testing, to allow output of the forward, reverse, pressure depenedent and net rates of progress for a more thorough comparison to Cantera (specifically, to quantify floating point errors for net production rates near equilibrium) ktype : :class:`KernelType` [KernelType.jacobian] The type of wrapper to generate Keyword Arguments ----------------- file_base: str Used for creation of libraries for :param:`ktype`==KernelType.dummy -- the base filename (generator name) for this library additional_inputs: list of str [[]] Use to supply additional input argument names to the generator process; currently this is only used for :param:`ktype`==KernelType.dummy Returns ------- None """ utils.check_lang(lang) source_dir = os.path.abspath(source_dir) if out_dir is None: out_dir = os.getcwd() if obj_dir is None: obj_dir = os.path.join(os.getcwd(), 'obj') if build_dir is None: build_dir = os.path.join(os.getcwd(), 'build', distutils_dir_name('temp')) # get all abspaths out_dir = os.path.abspath(out_dir) obj_dir = os.path.abspath(obj_dir) build_dir = os.path.abspath(build_dir) shared = True # first generate the library lib = generate_library(lang, source_dir, out_dir=build_dir, obj_dir=obj_dir, shared=shared, ktype=ktype, file_base=kwargs.get('file_base', None)) lib = os.path.abspath(lib) extra_include_dirs = [] libraries = [] libdirs = [] rpath = '' if lang == 'opencl': extra_include_dirs.extend(site.CL_INC_DIR) libraries.extend(site.CL_LIBNAME) setupfile = 'pyjacob_setup.py.in' pyxfile = 'pyjacob_wrapper.pyx.in' # generate wrapper wrapper = generate_wrapper(lang, os.path.join(home_dir, pyxfile), build_dir, ktype=ktype, additional_outputs=additional_outputs, additional_inputs=kwargs.pop( 'additional_inputs', []), nice_name=kwargs.get('file_base', None)) # generate setup setup = generate_setup(lang, os.path.join(home_dir, setupfile), wrapper, home_dir, source_dir, build_dir, lib, extra_include_dirs, libraries, libdirs, ktype=ktype) # and build / run call = [ setup, 'build_ext', '--build-lib', out_dir, '--build-temp', obj_dir ] if rpath: call += ['--rpath', rpath] utils.run_with_our_python(call)