Ejemplo n.º 1
0
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 []
Ejemplo n.º 2
0
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()
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
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 []
Ejemplo n.º 5
0
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 []
Ejemplo n.º 6
0
    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()
Ejemplo n.º 7
0
    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()
Ejemplo n.º 8
0
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)