From 41a000ebcc24fdc54c0109ace8e825f437153094 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Wed, 19 Jun 2013 15:09:17 -0400 Subject: [PATCH] Create loopy.library, move stuff there --- loopy/__init__.py | 14 ++-- loopy/kernel/__init__.py | 10 +-- loopy/kernel/data.py | 138 ------------------------------- loopy/library/__init__.py | 0 loopy/library/function.py | 91 ++++++++++++++++++++ loopy/library/preamble.py | 78 +++++++++++++++++ loopy/{ => library}/reduction.py | 0 loopy/library/symbol.py | 45 ++++++++++ loopy/symbolic.py | 4 +- setup.py | 1 + 10 files changed, 229 insertions(+), 152 deletions(-) create mode 100644 loopy/library/__init__.py create mode 100644 loopy/library/function.py create mode 100644 loopy/library/preamble.py rename loopy/{ => library}/reduction.py (100%) create mode 100644 loopy/library/symbol.py diff --git a/loopy/__init__.py b/loopy/__init__.py index b374041f7..5ae1a1291 100644 --- a/loopy/__init__.py +++ b/loopy/__init__.py @@ -41,14 +41,16 @@ from loopy.symbolic import ExpandingIdentityMapper, ExpandingSubstitutionMapper # {{{ imported user interface -from loopy.kernel.data import ( - ValueArg, GlobalArg, ConstantArg, ImageArg, - +from loopy.library.function import ( default_function_mangler, single_arg_function_mangler, - opencl_function_mangler, + opencl_function_mangler) - default_preamble_generator, +from loopy.library.preamble import default_preamble_generator +from loopy.library.symbol import opencl_symbol_mangler + +from loopy.kernel.data import ( + ValueArg, GlobalArg, ConstantArg, ImageArg, Instruction) from loopy.kernel import LoopKernel @@ -56,7 +58,7 @@ from loopy.kernel.tools import ( get_dot_dependency_graph, add_argument_dtypes, add_and_infer_argument_dtypes) from loopy.kernel.creation import make_kernel -from loopy.reduction import register_reduction_parser +from loopy.library.reduction import register_reduction_parser from loopy.subst import extract_subst, expand_subst from loopy.precompute import precompute from loopy.padding import (split_arg_axis, find_padding_multiple, diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py index b2baf97e7..314da630a 100644 --- a/loopy/kernel/__init__.py +++ b/loopy/kernel/__init__.py @@ -33,15 +33,13 @@ import re from pytools import UniqueNameGenerator, generate_unique_possibilities -from loopy.kernel.data import ( +from loopy.library.function import ( default_function_mangler, opencl_function_mangler, - single_arg_function_mangler, + single_arg_function_mangler) - opencl_symbol_mangler, - - default_preamble_generator, - ) +from loopy.library.symbol import opencl_symbol_mangler +from loopy.library.preamble import default_preamble_generator class CannotBranchDomainTree(RuntimeError): diff --git a/loopy/kernel/data.py b/loopy/kernel/data.py index 6a4ac4038..9de7f133e 100644 --- a/loopy/kernel/data.py +++ b/loopy/kernel/data.py @@ -446,142 +446,4 @@ class Instruction(Record): # }}} - -# {{{ function manglers / dtype getters - -def default_function_mangler(name, arg_dtypes): - from loopy.reduction import reduction_function_mangler - - manglers = [reduction_function_mangler] - for mangler in manglers: - result = mangler(name, arg_dtypes) - if result is not None: - return result - - return None - - -def opencl_function_mangler(name, arg_dtypes): - if name in ["max", "min"] and len(arg_dtypes) == 2: - dtype = np.find_common_type([], arg_dtypes) - - if dtype.kind == "c": - raise RuntimeError("min/max do not support complex numbers") - - if dtype.kind == "f": - name = "f" + name - - return dtype, name - - if name in "atan2" and len(arg_dtypes) == 2: - return arg_dtypes[0], name - - if len(arg_dtypes) == 1: - arg_dtype, = arg_dtypes - - if arg_dtype.kind == "c": - if arg_dtype == np.complex64: - tpname = "cfloat" - elif arg_dtype == np.complex128: - tpname = "cdouble" - else: - raise RuntimeError("unexpected complex type '%s'" % arg_dtype) - - if name in ["sqrt", "exp", "log", - "sin", "cos", "tan", - "sinh", "cosh", "tanh", - "conj"]: - return arg_dtype, "%s_%s" % (tpname, name) - - if name in ["real", "imag", "abs"]: - return np.dtype(arg_dtype.type(0).real), "%s_%s" % (tpname, name) - - if name == "dot": - scalar_dtype, offset, field_name = arg_dtypes[0].fields["s0"] - return scalar_dtype, name - - return None - - -def single_arg_function_mangler(name, arg_dtypes): - if len(arg_dtypes) == 1: - dtype, = arg_dtypes - return dtype, name - - return None - - -def opencl_symbol_mangler(name): - # FIXME: should be more picky about exact names - if name.startswith("FLT_"): - return np.dtype(np.float32), name - elif name.startswith("DBL_"): - return np.dtype(np.float64), name - elif name.startswith("M_"): - if name.endswith("_F"): - return np.dtype(np.float32), name - else: - return np.dtype(np.float64), name - elif name == "INFINITY": - return np.dtype(np.float32), name - else: - return None - -# }}} - - -# {{{ preamble generators - -def default_preamble_generator(seen_dtypes, seen_functions): - from loopy.reduction import reduction_preamble_generator - - for result in reduction_preamble_generator(seen_dtypes, seen_functions): - yield result - - has_double = False - has_complex = False - - for dtype in seen_dtypes: - if dtype in [np.float64, np.complex128]: - has_double = True - if dtype.kind == "c": - has_complex = True - - if has_double: - yield ("00_enable_double", """ - #pragma OPENCL EXTENSION cl_khr_fp64: enable - """) - - if has_complex: - if has_double: - yield ("10_include_complex_header", """ - #define PYOPENCL_DEFINE_CDOUBLE - - #include <pyopencl-complex.h> - """) - else: - yield ("10_include_complex_header", """ - #include <pyopencl-complex.h> - """) - - c_funcs = set(c_name for name, c_name, arg_dtypes in seen_functions) - if "int_floor_div" in c_funcs: - yield ("05_int_floor_div", """ - #define int_floor_div(a,b) \ - (( (a) - \ - ( ( (a)<0 ) != ( (b)<0 )) \ - *( (b) + ( (b)<0 ) - ( (b)>=0 ) )) \ - / (b) ) - """) - - if "int_floor_div_pos_b" in c_funcs: - yield ("05_int_floor_div_pos_b", """ - #define int_floor_div_pos_b(a,b) ( \ - ( (a) - ( ((a)<0) ? ((b)-1) : 0 ) ) / (b) \ - ) - """) - - -# }}} - # vim: foldmethod=marker diff --git a/loopy/library/__init__.py b/loopy/library/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/loopy/library/function.py b/loopy/library/function.py new file mode 100644 index 000000000..fcae07b6b --- /dev/null +++ b/loopy/library/function.py @@ -0,0 +1,91 @@ +from __future__ import division + +__copyright__ = "Copyright (C) 2012 Andreas Kloeckner" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + + +import numpy as np + + +def default_function_mangler(name, arg_dtypes): + from loopy.library.reduction import reduction_function_mangler + + manglers = [reduction_function_mangler] + for mangler in manglers: + result = mangler(name, arg_dtypes) + if result is not None: + return result + + return None + + +def opencl_function_mangler(name, arg_dtypes): + if name in ["max", "min"] and len(arg_dtypes) == 2: + dtype = np.find_common_type([], arg_dtypes) + + if dtype.kind == "c": + raise RuntimeError("min/max do not support complex numbers") + + if dtype.kind == "f": + name = "f" + name + + return dtype, name + + if name in "atan2" and len(arg_dtypes) == 2: + return arg_dtypes[0], name + + if len(arg_dtypes) == 1: + arg_dtype, = arg_dtypes + + if arg_dtype.kind == "c": + if arg_dtype == np.complex64: + tpname = "cfloat" + elif arg_dtype == np.complex128: + tpname = "cdouble" + else: + raise RuntimeError("unexpected complex type '%s'" % arg_dtype) + + if name in ["sqrt", "exp", "log", + "sin", "cos", "tan", + "sinh", "cosh", "tanh", + "conj"]: + return arg_dtype, "%s_%s" % (tpname, name) + + if name in ["real", "imag", "abs"]: + return np.dtype(arg_dtype.type(0).real), "%s_%s" % (tpname, name) + + if name == "dot": + scalar_dtype, offset, field_name = arg_dtypes[0].fields["s0"] + return scalar_dtype, name + + return None + + +def single_arg_function_mangler(name, arg_dtypes): + if len(arg_dtypes) == 1: + dtype, = arg_dtypes + return dtype, name + + return None + + +# vim: foldmethod=marker diff --git a/loopy/library/preamble.py b/loopy/library/preamble.py new file mode 100644 index 000000000..590320b05 --- /dev/null +++ b/loopy/library/preamble.py @@ -0,0 +1,78 @@ +from __future__ import division + +__copyright__ = "Copyright (C) 2012 Andreas Kloeckner" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + + +import numpy as np + + +def default_preamble_generator(seen_dtypes, seen_functions): + from loopy.library.reduction import reduction_preamble_generator + + for result in reduction_preamble_generator(seen_dtypes, seen_functions): + yield result + + has_double = False + has_complex = False + + for dtype in seen_dtypes: + if dtype in [np.float64, np.complex128]: + has_double = True + if dtype.kind == "c": + has_complex = True + + if has_double: + yield ("00_enable_double", """ + #pragma OPENCL EXTENSION cl_khr_fp64: enable + """) + + if has_complex: + if has_double: + yield ("10_include_complex_header", """ + #define PYOPENCL_DEFINE_CDOUBLE + + #include <pyopencl-complex.h> + """) + else: + yield ("10_include_complex_header", """ + #include <pyopencl-complex.h> + """) + + c_funcs = set(c_name for name, c_name, arg_dtypes in seen_functions) + if "int_floor_div" in c_funcs: + yield ("05_int_floor_div", """ + #define int_floor_div(a,b) \ + (( (a) - \ + ( ( (a)<0 ) != ( (b)<0 )) \ + *( (b) + ( (b)<0 ) - ( (b)>=0 ) )) \ + / (b) ) + """) + + if "int_floor_div_pos_b" in c_funcs: + yield ("05_int_floor_div_pos_b", """ + #define int_floor_div_pos_b(a,b) ( \ + ( (a) - ( ((a)<0) ? ((b)-1) : 0 ) ) / (b) \ + ) + """) + +# vim: foldmethod=marker diff --git a/loopy/reduction.py b/loopy/library/reduction.py similarity index 100% rename from loopy/reduction.py rename to loopy/library/reduction.py diff --git a/loopy/library/symbol.py b/loopy/library/symbol.py new file mode 100644 index 000000000..4ad22d58c --- /dev/null +++ b/loopy/library/symbol.py @@ -0,0 +1,45 @@ +from __future__ import division + +__copyright__ = "Copyright (C) 2012 Andreas Kloeckner" + +__license__ = """ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +""" + + +import numpy as np + + +def opencl_symbol_mangler(name): + # FIXME: should be more picky about exact names + if name.startswith("FLT_"): + return np.dtype(np.float32), name + elif name.startswith("DBL_"): + return np.dtype(np.float64), name + elif name.startswith("M_"): + if name.endswith("_F"): + return np.dtype(np.float32), name + else: + return np.dtype(np.float64), name + elif name == "INFINITY": + return np.dtype(np.float32), name + else: + return None + +# vim: foldmethod=marker diff --git a/loopy/symbolic.py b/loopy/symbolic.py index 950dcafb5..2352269d4 100644 --- a/loopy/symbolic.py +++ b/loopy/symbolic.py @@ -103,7 +103,7 @@ class Reduction(AlgebraicLeaf): assert isinstance(inames, tuple) if isinstance(operation, str): - from loopy.reduction import parse_reduction_op + from loopy.library.reduction import parse_reduction_op operation = parse_reduction_op(operation) self.operation = operation @@ -613,7 +613,7 @@ class FunctionToPrimitiveMapper(IdentityMapper): else: # see if 'name' is an existing reduction op - from loopy.reduction import parse_reduction_op + from loopy.library.reduction import parse_reduction_op if parse_reduction_op(name): if len(expr.parameters) != 2: raise RuntimeError("invalid invocation of " diff --git a/setup.py b/setup.py index 65a5f37e3..795af0723 100644 --- a/setup.py +++ b/setup.py @@ -53,6 +53,7 @@ setup(name="loo.py", "loopy", "loopy.codegen", "loopy.kernel", + "loopy.library", ], # 2to3 invocation -- GitLab