diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e371192f98f3004c0c3949fe91a5ec48b9296862..2f7b3f008c4677660951f67ca435fbbdf6ed8d14 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -77,3 +77,13 @@ Python 2.7 with legacy PyOpenCL: # - amd-cl-cpu # except: # - tags + +CentOS binary: + script: + - (cd build-helpers; ./make-linux-build-docker.sh --nodate) + - (cd ./build-helpers; ./loopy-centos6 ../examples/fortran/sparse.floopy) + artifacts: + paths: + - build-helpers/loopy-centos6 + tags: + - docker diff --git a/bin/loopy b/bin/loopy index 8291bdd3bfe5c157fca5bc4ad60ced2839ae529f..b169c6296acd453cf4183ee603813d186119d317 100644 --- a/bin/loopy +++ b/bin/loopy @@ -64,7 +64,7 @@ def main(): help="Defaults to stdout ('-').", nargs='?') parser.add_argument("--lang", metavar="LANGUAGE", help="loopy|fortran") parser.add_argument("--target", choices=( - "opencl", "ispc", "ispc-occa", "c", "cuda"), + "opencl", "ispc", "ispc-occa", "c", "c-fortran", "cuda"), default="opencl") parser.add_argument("--name") parser.add_argument("--transform") @@ -86,6 +86,9 @@ def main(): elif args.target == "c": from loopy.target.c import CTarget target = CTarget() + elif args.target == "c-fortran": + from loopy.target.c import CTarget + target = CTarget(fortran_abi=True) elif args.target == "cuda": from loopy.target.cuda import CudaTarget target = CudaTarget() @@ -102,10 +105,13 @@ def main(): _, ext = splitext(args.infile) lang = { + ".py": "loopy", ".loopy": "loopy", ".floopy": "fortran", ".f90": "fortran", ".fpp": "fortran", + ".f": "fortran", + ".f77": "fortran", }.get(ext) with open(args.infile, "r") as infile_fd: infile_content = infile_fd.read() @@ -221,16 +227,25 @@ def main(): code = "\n\n".join(codes) + # {{{ edit code if requested + import os edit_kernel_env = os.environ.get("LOOPY_EDIT_KERNEL") - if (args.edit_code - or ( - edit_kernel_env is not None - and - any(edit_kernel_env.lower() in k.name.lower() for k in kernels))): + need_edit = args.edit_code + if not need_edit and edit_kernel_env is not None: + # Do not replace with "any()"--Py2.6/2.7 bug doesn't like + # comprehensions in functions with exec(). + + for k in kernels: + if edit_kernel_env.lower() in k.name.lower(): + need_edit = True + + if need_edit: from pytools import invoke_editor code = invoke_editor(code, filename="edit.cl") + # }}} + if outfile == "-": sys.stdout.write(code) else: diff --git a/build-helpers/loopy.spec b/build-helpers/loopy.spec index 31162a2c6157504cc1363c95ad380780809865bd..14116ec539381137e0423855550773a43ad423d6 100644 --- a/build-helpers/loopy.spec +++ b/build-helpers/loopy.spec @@ -10,9 +10,16 @@ debug = False from os.path import expanduser +import packaging # pip install packaging to add + a = Analysis(['../bin/loopy'], pathex=[expanduser('~/src/loopy')], - hiddenimports=["appdirs"], + hiddenimports=[ + "appdirs", + "packaging.markers", + "packaging.specifiers", + "packaging.version", + ], hookspath=None, runtime_hooks=None, excludes=["hedge", "meshpy", "pyopencl", "PIL"] diff --git a/build-helpers/make-linux-build-docker-inner-part-2.sh b/build-helpers/make-linux-build-docker-inner-part-2.sh new file mode 100755 index 0000000000000000000000000000000000000000..d6f3ff3266192aec6b1761b771320966432d9166 --- /dev/null +++ b/build-helpers/make-linux-build-docker-inner-part-2.sh @@ -0,0 +1,31 @@ +#! /bin/bash + +set -e +set -x + +VENV_VERSION="virtualenv-1.9.1" +rm -Rf "$VENV_VERSION" +curl -k https://pypi.python.org/packages/source/v/virtualenv/$VENV_VERSION.tar.gz | tar xfz - + +$VENV_VERSION/virtualenv.py --system-site-packages --no-setuptools .env + +source .env/bin/activate + +curl -k https://ssl.tiker.net/software/ez_setup.py | python - +curl -k https://gitlab.tiker.net/inducer/pip/raw/7.0.3/contrib/get-pip.py | python - + +pip install packaging + +PYTHON_VER=$(python -c 'import sys; print(".".join(str(s) for s in sys.version_info[:2]))') +pip install git+https://github.com/pyinstaller/pyinstaller.git@413c37bec126c0bd26084813593f65128966b4b7 + +git clone --recursive git://github.com/inducer/loopy +cd loopy + +grep -v pyopencl requirements.txt > myreq.txt +pip install -r myreq.txt +python setup.py install + +chown -R user /tmp/build + +su user -p -c "cd /tmp/build && source .env/bin/activate && cd loopy && ./build-helpers/run-pyinstaller.sh" diff --git a/build-helpers/make-linux-build-docker-inner.sh b/build-helpers/make-linux-build-docker-inner.sh index 6b72639e0de24ee7e424a6157de2064e5beee978..119609a3c1767dd1e5ce1781f27c946781d1a79b 100755 --- a/build-helpers/make-linux-build-docker-inner.sh +++ b/build-helpers/make-linux-build-docker-inner.sh @@ -8,28 +8,8 @@ cd /tmp/build useradd -d /home/user -m -s /bin/bash user -yum install -y git python-devel tar gcc gcc-c++ mercurial numpy libffi-devel +yum install -y centos-release-SCL +yum install -y git python27 python27-python-devel python27-numpy tar gcc gcc-c++ mercurial libffi-devel -VENV_VERSION="virtualenv-1.9.1" -rm -Rf "$VENV_VERSION" -curl -k https://pypi.python.org/packages/source/v/virtualenv/$VENV_VERSION.tar.gz | tar xfz - +scl enable python27 /mnt/make-linux-build-docker-inner-part-2.sh -VIRTUALENV=virtualenv -$VENV_VERSION/virtualenv.py --system-site-packages --no-setuptools .env - -source .env/bin/activate - -curl -k https://ssl.tiker.net/software/ez_setup.py | python - -curl -k https://gitlab.tiker.net/inducer/pip/raw/7.0.3/contrib/get-pip.py | python - - -pip install pyinstaller -git clone --recursive git://github.com/inducer/loopy -cd loopy - -grep -v pyopencl requirements.txt > myreq.txt -pip install -r myreq.txt -python setup.py install - -chown -R user /tmp/build - -su user -p -c "cd /tmp/build && source .env/bin/activate && cd loopy && ./build-helpers/run-pyinstaller.sh" diff --git a/build-helpers/make-linux-build-docker.sh b/build-helpers/make-linux-build-docker.sh index 90684a267e98f1976a31fd3036b824d2c2cdc1d8..fb0cfb587d654698800bfdc827259691bc056fb7 100755 --- a/build-helpers/make-linux-build-docker.sh +++ b/build-helpers/make-linux-build-docker.sh @@ -2,9 +2,19 @@ # should be run in this directory (build-helpers) +if test "$1" = "--nodate"; then + TGT_NAME=loopy-centos6 +else + TGT_NAME=loopy-centos6-$(date +"%Y-%m-%d") +fi + +echo "Generating $TGT_NAME..." + set -e set -x +docker pull centos:6 + CNT=$(docker create -t -v $(pwd):/mnt centos:6 /mnt/make-linux-build-docker-inner.sh) echo "working in container $CNT" @@ -12,7 +22,7 @@ docker start -i $CNT docker cp $CNT:/tmp/build/loopy/dist/loopy $(pwd) || true -mv loopy loopy-centos6-$(date +"%Y-%m-%d") +mv loopy $TGT_NAME docker rm $CNT diff --git a/doc/index.rst b/doc/index.rst index 73fd85f52fff0068d5a91e54c8ea37d4524185ee..19bbe87727e8d3ffa5aa0cb1c31e4e206bd97b3e 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -18,6 +18,29 @@ When you run this script, the following kernel is generated, compiled, and execu (See the full example for how to print the generated code.) +Want to try out loopy? +---------------------- + +There's no need to go through :ref:`installation` if you'd just like to get a +feel for what loopy is. Instead, you may +`download a self-contained Linux binary <https://gitlab.tiker.net/inducer/loopy/builds/1989/artifacts/browse/build-helpers/>`_. +This is purposefully built on an ancient Linux distribution, so it should work +on most versions of Linux that are currently out there. + +Once you have the binary, do the following:: + + chmod +x ./loopy-centos6 + ./loopy-centos6 --target=opencl hello-loopy-lp.py + ./loopy-centos6 --target=cuda hello-loopy-lp.py + ./loopy-centos6 --target=ispc hello-loopy-lp.py + +Grab the example here: :download:`examples/python/hello-loopy.py <../examples/python/hello-loopy-lp.py>`. + +You may also donwload the most recent version by going to the `list of builds +<https://gitlab.tiker.net/inducer/loopy/builds>`_, clicking on the newest one +of type "CentOS binary", clicking on "Browse" under "Build Artifacts", then +navigating to "build-helpers", and downloading the binary from there. + Places on the web related to Loopy ---------------------------------- diff --git a/doc/misc.rst b/doc/misc.rst index a07a772eb5bb97ce98414b80038057476bd27dd1..fc170120f894f2cf5645d86621e56680019d3fae 100644 --- a/doc/misc.rst +++ b/doc/misc.rst @@ -5,7 +5,7 @@ Installation This command should install :mod:`loopy`:: - pip install https://github.com/inducer/loopy/tarball/master + pip install loopy You may need to run this with :command:`sudo`. If you don't already have `pip <https://pypi.python.org/pypi/pip>`_, @@ -27,14 +27,17 @@ You may also clone its git repository:: User-visible Changes ==================== -Version 2014.1 +Version 2016.2 -------------- .. note:: This version is currently under development. You can get snapshots from - PyOpenCL's `git repository <https://github.com/inducer/loopy>`_ + loopy's `git repository <https://github.com/inducer/loopy>`_ -* Initial release. +Version 2016.1 +-------------- + +* Initial release. .. _license: diff --git a/examples/python/hello-loopy-lp.py b/examples/python/hello-loopy-lp.py index 382aadc097352ab7328b9ef956e0c0379d06a2cb..0ba44d6eccb18236ac13e17ca747318af3962634 100644 --- a/examples/python/hello-loopy-lp.py +++ b/examples/python/hello-loopy-lp.py @@ -8,4 +8,4 @@ knl = lp.make_kernel( "out[i] = 2*a[i]") knl = lp.add_and_infer_dtypes(knl, dict(a=np.float32)) -lp_knl = lp.split_iname(knl, "i", 128, outer_tag="g.0", inner_tag="l.0") +lp_knl = lp.split_iname(knl, "i", 8, outer_tag="g.0", inner_tag="l.0") diff --git a/loopy/frontend/fortran/translator.py b/loopy/frontend/fortran/translator.py index c708fc4a1d2980dbe36cd243678f355d441fbdd7..53ea602f1d9b0a5b4fd9b04bc2486d7daae0ca5f 100644 --- a/loopy/frontend/fortran/translator.py +++ b/loopy/frontend/fortran/translator.py @@ -301,6 +301,7 @@ class F2LoopyTranslator(FTreeWalkerBase): TYPE_MAP = { ("real", "4"): np.float32, ("real", "8"): np.float64, + ("doubleprecision", ""): np.float64, ("complex", "8"): np.complex64, ("complex", "16"): np.complex128, @@ -339,6 +340,7 @@ class F2LoopyTranslator(FTreeWalkerBase): map_Integer = map_type_decl map_Real = map_type_decl map_Complex = map_type_decl + map_DoublePrecision = map_type_decl def map_Dimension(self, node): scope = self.scope_stack[-1] diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py index 46888e620501785073e2abf58180a5c6c93109d1..d125b0dfa964688e60d02fae242f2f1876b22f87 100644 --- a/loopy/kernel/__init__.py +++ b/loopy/kernel/__init__.py @@ -1155,7 +1155,7 @@ class LoopKernel(RecordWithoutPickling): # {{{ persistent hash key generation / comparison - hash_fields = [ + hash_fields = ( "domains", "instructions", "args", @@ -1173,9 +1173,9 @@ class LoopKernel(RecordWithoutPickling): "options", "state", "target", - ] + ) - comparison_fields = hash_fields + [ + comparison_fields = hash_fields + ( # Contains pymbolic expressions, hence a (small) headache to hash. # Likely not needed for hash uniqueness => headache avoided. "applied_iname_rewrites", @@ -1189,7 +1189,7 @@ class LoopKernel(RecordWithoutPickling): "preamble_generators", "function_manglers", "symbol_manglers", - ] + ) def update_persistent_hash(self, key_hash, key_builder): """Custom hash computation function for use with diff --git a/loopy/target/__init__.py b/loopy/target/__init__.py index b8c903fc12cccde4e764731580cc8cfc04151af3..ee28594a50ce8486702e13f0ee9bf01debb4f859 100644 --- a/loopy/target/__init__.py +++ b/loopy/target/__init__.py @@ -30,8 +30,8 @@ class TargetBase(object): # {{{ persistent hashing - hash_fields = [] - comparison_fields = [] + hash_fields = () + comparison_fields = () def update_persistent_hash(self, key_hash, key_builder): for field_name in self.hash_fields: diff --git a/loopy/target/c/__init__.py b/loopy/target/c/__init__.py index 0cf17992251778ee971298e736bd1080f6f36f13..73310c4db7ad590396377d1d757ebf8eb068a8e6 100644 --- a/loopy/target/c/__init__.py +++ b/loopy/target/c/__init__.py @@ -56,6 +56,13 @@ def _preamble_generator(kernel, seen_dtypes, seen_functions): class CTarget(TargetBase): + hash_fields = TargetBase.hash_fields + ("fortran_abi",) + comparison_fields = TargetBase.comparison_fields + ("fortran_abi",) + + def __init__(self, fortran_abi=False): + self.fortran_abi = fortran_abi + super(CTarget, self).__init__() + # {{{ types @memoize_method @@ -101,12 +108,16 @@ class CTarget(TargetBase): body, implemented_domains = kernel.target.generate_body( kernel, codegen_state) + name = kernel.name + if self.fortran_abi: + name += "_" + mod = Module([ FunctionBody( kernel.target.wrap_function_declaration( kernel, FunctionDeclaration( - Value("void", kernel.name), + Value("void", name), [iai.cgen_declarator for iai in impl_arg_info])), body) ]) @@ -234,7 +245,7 @@ class CTarget(TargetBase): def get_expression_to_code_mapper(self, codegen_state): from loopy.target.c.codegen.expression import LoopyCCodeMapper - return LoopyCCodeMapper(codegen_state) + return LoopyCCodeMapper(codegen_state, fortran_abi=self.fortran_abi) def wrap_temporary_decl(self, decl, is_local): return decl @@ -247,6 +258,11 @@ class CTarget(TargetBase): if not is_written: from cgen import Const result = Const(result) + + if self.fortran_abi: + from cgen import Pointer + result = Pointer(result) + return result def get_global_arg_decl(self, name, shape, dtype, is_written): diff --git a/loopy/target/c/codegen/expression.py b/loopy/target/c/codegen/expression.py index 2bf5c06bad405fba3a6a01f039cee0f4a133322c..d931ebf3373b7ab455787f5be7db7360cc042e66 100644 --- a/loopy/target/c/codegen/expression.py +++ b/loopy/target/c/codegen/expression.py @@ -42,13 +42,15 @@ from loopy.tools import is_integer # {{{ C code mapper class LoopyCCodeMapper(RecursiveMapper): - def __init__(self, codegen_state): + def __init__(self, codegen_state, fortran_abi=False): self.kernel = codegen_state.kernel self.codegen_state = codegen_state self.type_inf_mapper = TypeInferenceMapper(self.kernel) self.allow_complex = codegen_state.allow_complex + self.fortran_abi = fortran_abi + # {{{ helpers def infer_type(self, expr): @@ -108,6 +110,8 @@ class LoopyCCodeMapper(RecursiveMapper): "entry to loopy") def map_variable(self, expr, enclosing_prec, type_context): + prefix = "" + if expr.name in self.codegen_state.var_subst_map: if self.kernel.options.annotate_inames: return " /* %s */ %s" % ( @@ -131,12 +135,16 @@ class LoopyCCodeMapper(RecursiveMapper): raise RuntimeError("unsubscripted reference to array '%s'" % expr.name) + from loopy.kernel.data import ValueArg + if isinstance(arg, ValueArg) and self.fortran_abi: + prefix = "*" + result = self.kernel.mangle_symbol(expr.name) if result is not None: _, c_name = result - return c_name + return prefix + c_name - return expr.name + return prefix + expr.name def map_tagged_variable(self, expr, enclosing_prec, type_context): return expr.name diff --git a/loopy/target/cuda.py b/loopy/target/cuda.py index 4b3237515152965f1d7c0f7ddd271d25e3afb767..94a144cb972b10cd7a1d797adbd8d259e7eb64dc 100644 --- a/loopy/target/cuda.py +++ b/loopy/target/cuda.py @@ -169,6 +169,8 @@ class CudaTarget(CTarget): """ self.extern_c = extern_c + super(CudaTarget, self).__init__() + # {{{ library def function_manglers(self): diff --git a/loopy/target/ispc.py b/loopy/target/ispc.py index 4fcccf8ab7c938b13a6fa76253010f80a7465520..f28dc4e72e8bc639b7c0483a0b31c96beb29fec4 100644 --- a/loopy/target/ispc.py +++ b/loopy/target/ispc.py @@ -62,6 +62,8 @@ class ISPCTarget(CTarget): """ self.occa_mode = occa_mode + super(ISPCTarget, self).__init__() + # {{{ top-level codegen def generate_code(self, kernel, codegen_state, impl_arg_info): diff --git a/loopy/version.py b/loopy/version.py index 4154c3a59cd2e2db383db3e4670ce55365ede1c1..2b35b55e073359992a483f494d56b8d3a912fd64 100644 --- a/loopy/version.py +++ b/loopy/version.py @@ -32,4 +32,4 @@ except ImportError: else: _islpy_version = islpy.version.VERSION_TEXT -DATA_MODEL_VERSION = "v17-islpy%s" % _islpy_version +DATA_MODEL_VERSION = "v18-islpy%s" % _islpy_version diff --git a/requirements.txt b/requirements.txt index df54704f8091c6c4b8807c7d7b7b1d09d918cc9e..5dbc4b050f4dd688e038b994281e08e73ab3133b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,6 @@ hg+https://bitbucket.org/inducer/f2py # Optional, needed for using the C preprocessor on Fortran ply>=3.6 + +# This is needed for the pyinstaller executable to be usable. +packaging