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 `_.
+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
+`_, 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 `_,
@@ -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 `_
+ loopy's `git repository `_
-* 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