diff --git a/doc/array.rst b/doc/array.rst index 2be1742f3fbf0d407b9f11114aa441fe89a7853d..8c83e6663f007560a744953e0439a875981e56ea 100644 --- a/doc/array.rst +++ b/doc/array.rst @@ -126,7 +126,7 @@ never directly. * complex*complex * real+complex - *look* like they may do the right thing, but sliently do the wrong thing. + *look* like they may do the right thing, but silently do the wrong thing. The :class:`Array` Class ------------------------ @@ -179,8 +179,8 @@ Reductions See also :ref:`custom-reductions`. -Elementwise Functions on :class:`Arrray` Instances --------------------------------------------------- +Elementwise Functions on :class:`Array` Instances +------------------------------------------------- .. module:: pyopencl.clmath diff --git a/doc/index.rst b/doc/index.rst index ea711642adb2212675014f429643b87c79768513..bf981109164d3a16f1edc83ccd5f20b7181dc674 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -45,7 +45,7 @@ Tutorials and `Tom Deakin `_'s course `Hands-on OpenCL `_ contains both `lecture slides `_ - and `excercises (with solutions) `_ + and `exercises (with solutions) `_ (The course covers PyOpenCL as well as OpenCL's C and C++ APIs.) * PyOpenCL course at `PASI `_: Parts `1 `_ diff --git a/doc/misc.rst b/doc/misc.rst index e56830df8fa3f90dafe805b82f5e90adfaab7b4e..a3d3e638c2060834002bcb3b12f9fe1760263219 100644 --- a/doc/misc.rst +++ b/doc/misc.rst @@ -32,7 +32,7 @@ and then use the ``%%cl_kernel`` 'cell-magic' command. See `this notebook You can pass build options to be used for building the program executable by using the ``-o`` flag on the first line of the cell (next to the ``%%cl_kernel`` directive). For example: `%%cl_kernel -o "-cl-fast-relaxed-math"``. -There are also line magics: ``cl_load_edit_kernel`` which will load a file into the next cell (adding ``cl_kernel`` to the first line) and ``cl_kernel_from_file`` which will compile kernels from a file (as if you copy-and-pasted the contents of the file to a cell with ``cl_kernel``). Boths of these magics take options ``-f`` to specify the file and optionally ``-o`` for build options. +There are also line magics: ``cl_load_edit_kernel`` which will load a file into the next cell (adding ``cl_kernel`` to the first line) and ``cl_kernel_from_file`` which will compile kernels from a file (as if you copy-and-pasted the contents of the file to a cell with ``cl_kernel``). Both of these magics take options ``-f`` to specify the file and optionally ``-o`` for build options. .. versionadded:: 2014.1 @@ -164,7 +164,7 @@ Version 2015.2 * complex*complex * real+complex - *look* like they may do the right thing, but sliently do the wrong thing. + *look* like they may do the right thing, but silently do the wrong thing. * Rewrite of the wrapper layer to be based on CFFI * Pypy compatibility * Faster kernel invocation through Python launcher code generation @@ -331,7 +331,7 @@ Version 2011.1 * Add :ref:`memory-pools`. * Add vector types, see :class:`pyopencl.array.vec`. * Add :attr:`pyopencl.array.Array.strides`, :attr:`pyopencl.array.Array.flags`. - Allow the creation of arrys in C and Fortran order. + Allow the creation of arrays in C and Fortran order. * Add :func:`pyopencl.enqueue_copy`. Deprecate all other transfer functions. * Add support for numerous extensions, among them device fission. * Add a compiler cache. diff --git a/doc/runtime_memory.rst b/doc/runtime_memory.rst index e3312973ddd85aeabd55b48728ab6df8c3c04f49..f23a29ae4912173f1019b15fc53cc629fd78ab2f 100644 --- a/doc/runtime_memory.rst +++ b/doc/runtime_memory.rst @@ -96,7 +96,10 @@ Buffer .. function:: enqueue_fill_buffer(queue, mem, pattern, offset, size, wait_for=None) - :arg pattern: a buffer object (likely a :class:`numpy.ndarray`) + :arg mem: the on device :class:`Buffer` + :arg pattern: a buffer object (likely a :class:`numpy.ndarray`, eg. `np.uint32(0)`) + + Fills a buffer with the provided pattern |std-enqueue-blurb| @@ -104,6 +107,16 @@ Buffer .. versionadded:: 2011.2 +.. function:: enqueue_copy_buffer(queue, src, dst, byte_count=-1, src_offset=0, dst_offset=0, wait_for=None) + + :arg src: the source :class:`Buffer` + :arg dst: the destination device :class:`Buffer` + :arg byte_count: the number of bytes to copy + + Performs a device to device copy from `src` to `dst`. + + |std-enqueue-blurb| + .. _svm: Shared Virtual Memory (SVM) diff --git a/doc/tools.rst b/doc/tools.rst index 9c647b1992c6337cc58d73ec24d13e4ecb6a18af..967b8d34303f5fb6fbb86a697e3152baefd7d18b 100644 --- a/doc/tools.rst +++ b/doc/tools.rst @@ -91,7 +91,7 @@ not complicated:: .. method:: __call__(size) - Synoynm for :meth:`allocate` to match :class:`CLAllocator` interface. + Synonym for :meth:`allocate` to match :class:`CLAllocator` interface. .. versionadded: 2011.2 diff --git a/doc/types.rst b/doc/types.rst new file mode 100644 index 0000000000000000000000000000000000000000..ccc96fdd355737bc90e6ec1112b876ba30f1e7cb --- /dev/null +++ b/doc/types.rst @@ -0,0 +1,34 @@ +OpenCL Type Mapping +=================== + +.. module:: pyopencl.types + +.. _type-mappings: + +Scalar Types +------------ + +For ease of use, a the cltypes module provides convenient mapping from OpenCL type names +to their equivalent numpy types. This saves you from referring back to the OpenCL spec to +see that a cl_long is 64 bit unsigned integer. Use the module as follows: + +.. doctest:: + + >>> import numpy as np + >>> import pyopencl as cl + >>> import pyopencl.cltypes + >>> cl_uint = cl.cltypes.uint(42) # maps to numpy.uint32 + >>> cl_long = cl.cltypes.long(1235) # maps to numpy.int64 + >>> floats = np.empty((128,), dtype=cl.cltypes.float) # array of numpy.float32 + + +Vector Types +------------ +The corresponding vector types are also made available in the same package, allowing you to easily create +numpy arrays with the appropriate memory layout. + +.. doctest:: + + >>> import numpy as np + >>> array_of_float16 = np.empty((128,), dtype=cl.cltypes.float16) # array of float16 + diff --git a/pyopencl/array.py b/pyopencl/array.py index f3957bb0f981fd59a176b4408609c9fa5695a1c2..f40cfbbcd65d27f776f1fd60e2c37d79d431f516 100644 --- a/pyopencl/array.py +++ b/pyopencl/array.py @@ -28,7 +28,7 @@ OTHER DEALINGS IN THE SOFTWARE. """ import six -from six.moves import range, zip, reduce +from six.moves import range, reduce import numpy as np import pyopencl.elementwise as elementwise @@ -42,11 +42,12 @@ from pyopencl.compyte.array import ( ArrayFlags as _ArrayFlags, get_common_dtype as _get_common_dtype_base) from pyopencl.characterize import has_double_support +from pyopencl import cltypes def _get_common_dtype(obj1, obj2, queue): return _get_common_dtype_base(obj1, obj2, - has_double_support(queue.device)) + has_double_support(queue.device)) # Work around PyPy not currently supporting the object dtype. @@ -62,103 +63,20 @@ except: return False -# {{{ vector types - -class vec: # noqa - pass - - -def _create_vector_types(): - field_names = ["x", "y", "z", "w"] - - from pyopencl.tools import get_or_register_dtype - - vec.types = {} - vec.type_to_scalar_and_count = {} - - counts = [2, 3, 4, 8, 16] - - for base_name, base_type in [ - ('char', np.int8), - ('uchar', np.uint8), - ('short', np.int16), - ('ushort', np.uint16), - ('int', np.int32), - ('uint', np.uint32), - ('long', np.int64), - ('ulong', np.uint64), - ('float', np.float32), - ('double', np.float64), - ]: - for count in counts: - name = "%s%d" % (base_name, count) - - titles = field_names[:count] - - padded_count = count - if count == 3: - padded_count = 4 - - names = ["s%d" % i for i in range(count)] - while len(names) < padded_count: - names.append("padding%d" % (len(names)-count)) - - if len(titles) < len(names): - titles.extend((len(names)-len(titles))*[None]) - - try: - dtype = np.dtype(dict( - names=names, - formats=[base_type]*padded_count, - titles=titles)) - except NotImplementedError: - try: - dtype = np.dtype([((n, title), base_type) - for (n, title) in zip(names, titles)]) - except TypeError: - dtype = np.dtype([(n, base_type) for (n, title) - in zip(names, titles)]) - - get_or_register_dtype(name, dtype) - - setattr(vec, name, dtype) - - def create_array(dtype, count, padded_count, *args, **kwargs): - if len(args) < count: - from warnings import warn - warn("default values for make_xxx are deprecated;" - " instead specify all parameters or use" - " array.vec.zeros_xxx", DeprecationWarning) - padded_args = tuple(list(args)+[0]*(padded_count-len(args))) - array = eval("array(padded_args, dtype=dtype)", - dict(array=np.array, padded_args=padded_args, - dtype=dtype)) - for key, val in list(kwargs.items()): - array[key] = val - return array - - setattr(vec, "make_"+name, staticmethod(eval( - "lambda *args, **kwargs: create_array(dtype, %i, %i, " - "*args, **kwargs)" % (count, padded_count), - dict(create_array=create_array, dtype=dtype)))) - setattr(vec, "filled_"+name, staticmethod(eval( - "lambda val: vec.make_%s(*[val]*%i)" % (name, count)))) - setattr(vec, "zeros_"+name, - staticmethod(eval("lambda: vec.filled_%s(0)" % (name)))) - setattr(vec, "ones_"+name, - staticmethod(eval("lambda: vec.filled_%s(1)" % (name)))) - - vec.types[np.dtype(base_type), count] = dtype - vec.type_to_scalar_and_count[dtype] = np.dtype(base_type), count - - -_create_vector_types() +class VecLookupWarner(object): + def __getattr__(self, name): + from warnings import warn + warn("pyopencl.array.vec is deprecated. " + "Please use pyopencl.cltypes for OpenCL vector and scalar types", + DeprecationWarning, 2) + return getattr(cltypes, name) -# }}} +vec = VecLookupWarner() # {{{ helper functionality + def splay(queue, n, kernel_specific_max_wg_size=None): dev = queue.device max_work_items = _builtin_min(128, dev.max_work_group_size) diff --git a/pyopencl/cltypes.py b/pyopencl/cltypes.py new file mode 100644 index 0000000000000000000000000000000000000000..c8ff35c378bd1eb395e54dc0efa5ce6a21ff9b85 --- /dev/null +++ b/pyopencl/cltypes.py @@ -0,0 +1,127 @@ +# encoding: utf8 + +__copyright__ = "Copyright (C) 2016 Jonathan Mackenzie" + +__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 +from pyopencl.tools import get_or_register_dtype +import warnings + +if __file__.endswith('array.py'): + warnings.warn("pyopencl.array.vec is deprecated. Please use pyopencl.cltypes") + +""" +This file provides a type mapping from OpenCl type names to their numpy equivalents +""" + +char = np.int8 +uchar = np.uint8 +short = np.int16 +ushort = np.uint16 +int = np.int32 +uint = np.uint32 +long = np.int64 +ulong = np.uint64 +half = np.float16 +float = np.float32 +double = np.float64 + + +# {{{ vector types + + +def _create_vector_types(): + _mapping = [(k, globals()[k]) for k in + ['char', 'uchar', 'short', 'ushort', 'int', + 'uint', 'long', 'ulong', 'float', 'double']] + + def set_global(key, val): + globals()[key] = val + + field_names = ["x", "y", "z", "w"] + + set_global('types', {}) + set_global('type_to_scalar_and_count', {}) + + counts = [2, 3, 4, 8, 16] + + for base_name, base_type in _mapping: + for count in counts: + name = "%s%d" % (base_name, count) + + titles = field_names[:count] + + padded_count = count + if count == 3: + padded_count = 4 + + names = ["s%d" % i for i in range(count)] + while len(names) < padded_count: + names.append("padding%d" % (len(names) - count)) + + if len(titles) < len(names): + titles.extend((len(names) - len(titles)) * [None]) + + try: + dtype = np.dtype(dict( + names=names, + formats=[base_type] * padded_count, + titles=titles)) + except NotImplementedError: + try: + dtype = np.dtype([((n, title), base_type) + for (n, title) in zip(names, titles)]) + except TypeError: + dtype = np.dtype([(n, base_type) for (n, title) + in zip(names, titles)]) + + get_or_register_dtype(name, dtype) + + set_global(name, dtype) + + def create_array(dtype, count, padded_count, *args, **kwargs): + if len(args) < count: + from warnings import warn + warn("default values for make_xxx are deprecated;" + " instead specify all parameters or use" + " cltypes.zeros_xxx", DeprecationWarning) + padded_args = tuple(list(args) + [0] * (padded_count - len(args))) + array = eval("array(padded_args, dtype=dtype)", + dict(array=np.array, padded_args=padded_args, + dtype=dtype)) + for key, val in list(kwargs.items()): + array[key] = val + return array + + set_global("make_" + name, eval( + "lambda *args, **kwargs: create_array(dtype, %i, %i, " + "*args, **kwargs)" % (count, padded_count), + dict(create_array=create_array, dtype=dtype))) + set_global("filled_" + name, eval( + "lambda val: make_%s(*[val]*%i)" % (name, count))) + set_global("zeros_" + name, eval("lambda: filled_%s(0)" % (name))) + set_global("ones_" + name, eval("lambda: filled_%s(1)" % (name))) + + globals()['types'][np.dtype(base_type), count] = dtype + globals()['type_to_scalar_and_count'][dtype] = np.dtype(base_type), count + + +_create_vector_types() +# }}}