From 6929a6c757501da611970ce48733bd86645243d1 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Fri, 5 Oct 2012 02:21:12 -0400 Subject: [PATCH] Clean up Array constructor, remove some deprecated stuff. --- doc/source/array.rst | 18 +++--- doc/source/misc.rst | 2 + pyopencl/array.py | 142 ++++++++++++++++++------------------------- 3 files changed, 70 insertions(+), 92 deletions(-) diff --git a/doc/source/array.rst b/doc/source/array.rst index cf0f080c..b8276109 100644 --- a/doc/source/array.rst +++ b/doc/source/array.rst @@ -112,23 +112,21 @@ The :class:`Array` Class An alias for :class:`pyopencl.tools.CLAllocator`. -.. class:: Array(cqa, shape, dtype, order="C", *, allocator=None, base=None, data=None, queue=None) +.. class:: Array(cqa, shape, dtype, order="C", *, allocator=None, base=None, data=None) A :class:`numpy.ndarray` work-alike that stores its data and performs its computations on the compute device. *shape* and *dtype* work exactly as in :mod:`numpy`. Arithmetic methods in :class:`Array` support the broadcasting of scalars. (e.g. `array+5`) - *cqa* can be a :class:`pyopencl.Context`, :class:`pyopencl.CommandQueue` - or an allocator, as described below. If it is either of the latter two, the *queue* - or *allocator* arguments may not be passed. + *cqa* must be a :class:`pyopencl.CommandQueue`. *cqa* + specifies the queue in which the array carries out its + computations by default. *cqa* will at some point be renamed *queue*, + so it should be considered 'positional-only'. - *queue* (or *cqa*, as the case may be) specifies the queue in which the array - carries out its computations by default. - - *allocator* is a callable that, upon being called with an argument of the number - of bytes to be allocated, returns an :class:`pyopencl.Buffer` object. - (See :class:`DefaultAllocator`.) + *allocator* may be `None` or a callable that, upon being called with an + argument of the number of bytes to be allocated, returns an + :class:`pyopencl.Buffer` object. (See :class:`DefaultAllocator`.) .. versionchanged:: 2011.1 Renamed *context* to *cqa*, made it general-purpose. diff --git a/doc/source/misc.rst b/doc/source/misc.rst index f6f456a8..0d4f937e 100644 --- a/doc/source/misc.rst +++ b/doc/source/misc.rst @@ -89,6 +89,8 @@ Version 2012.2 `their programming guide <http://developer.amd.com/sdks/AMDAPPSDK/assets/AMD_Accelerated_Parallel_Processing_OpenCL_Programming_Guide.pdf>`_. * Deprecated :func:`pyopencl.tools.register_dtype` in favor of :func:`pyopencl.tools.get_or_register_dtype`. +* Clean up the :class:`pyopencl.array.Array` constructor interface. Deprecate + arrays with :attr:`pyopencl.array.Array.queue` equal to *None*. Version 2012.1 -------------- diff --git a/pyopencl/array.py b/pyopencl/array.py index fd40e16c..d03dd596 100644 --- a/pyopencl/array.py +++ b/pyopencl/array.py @@ -195,18 +195,6 @@ def elwise_kernel_runner(kernel_getter): DefaultAllocator = cl.CLAllocator - - - -def _should_be_cqa(what): - from warnings import warn - warn("'%s' should be specified as the frst" - "('cqa') argument, " - "not in the '%s' keyword argument. " - "This will be continue to be accepted througout " - "versions 2011.x of PyOpenCL." % (what, what), - DeprecationWarning, 3) - # }}} # {{{ array class @@ -221,7 +209,15 @@ class Array(object): def __init__(self, cqa, shape, dtype, order="C", allocator=None, data=None, queue=None, strides=None): - # {{{ backward compatibility for pre-cqa days + # {{{ backward compatibility + + from warnings import warn + if queue is not None: + warn("Passing the queue to the array through anything but the " + "first argument of the Array constructor is deprecated. " + "This will be continue to be accepted throughout the 2013.[0-6] " + "versions of PyOpenCL.", + DeprecationWarning, 2) if isinstance(cqa, cl.CommandQueue): if queue is not None: @@ -229,27 +225,37 @@ class Array(object): "'queue' arguments") queue = cqa - if allocator is None: - context = queue.context - allocator = DefaultAllocator(context) - elif isinstance(cqa, cl.Context): - if queue is not None: - _should_be_cqa("queue") + warn("Passing a context for the 'cqa' parameter is deprecated. " + "This usage will be continue to be accepted throughout the 2013.[0-6] " + "versions of PyOpenCL.", + DeprecationWarning, 2) + if queue is not None: + raise TypeError("may not pass a context and a queue " + "(just pass the queue)") if allocator is not None: - _should_be_cqa("allocator") - else: - allocator = DefaultAllocator(cqa) + raise TypeError("may not pass a context and an allocator " + "(just pass the queue)") else: # cqa is assumed to be an allocator + warn("Passing an allocator for the 'cqa' parameter is deprecated. " + "This usage will be continue to be accepted throughout the 2013.[0-6] " + "versions of PyOpenCL.", + DeprecationWarning, 2) if allocator is not None: raise TypeError("can't specify allocator in 'cqa' and " "'allocator' arguments") allocator = cqa + if queue is None: + warn("Queue-less arrays are deprecated. " + "They will continue to work throughout the 2013.[0-6] " + "versions of PyOpenCL.", + DeprecationWarning, 2) + # }}} # invariant here: allocator, queue set @@ -298,12 +304,20 @@ class Array(object): self.strides = strides self.size = s - self.nbytes = self.dtype.itemsize * self.size + nbytes = self.nbytes = self.dtype.itemsize * self.size self.allocator = allocator + if data is None: if self.size: - self.data = self.allocator(self.size * self.dtype.itemsize) + if allocator is None: + # FIXME remove me when queues become required + if queue is not None: + context = queue.context + + self.data = cl.Buffer(context, cl.mem_flags.READ_WRITE, nbytes) + else: + self.data = self.allocator(self.size * self.dtype.itemsize) else: self.data = None else: @@ -858,52 +872,30 @@ def as_strided(ary, shape=None, strides=None): # {{{ creation helpers -def to_device(*args, **kwargs): +def to_device(queue, ary, allocator=None, async=False): """Converts a numpy array to a :class:`Array`.""" - def _to_device(queue, ary, allocator=None, async=False): - if ary.dtype == object: - raise RuntimeError("to_device does not work on object arrays.") - - result = Array(queue, ary.shape, ary.dtype, - allocator=allocator, strides=ary.strides) - result.set(ary, async=async) - return result - - if isinstance(args[0], cl.Context): - from warnings import warn - warn("Passing a context as first argument is deprecated. " - "This will be continue to be accepted througout " - "versions 2011.x of PyOpenCL.", - DeprecationWarning, 2) - args = args[1:] + if ary.dtype == object: + raise RuntimeError("to_device does not work on object arrays.") - return _to_device(*args, **kwargs) + result = Array(queue, ary.shape, ary.dtype, + allocator=allocator, strides=ary.strides) + result.set(ary, async=async) + return result empty = Array -def zeros(*args, **kwargs): +def zeros(queue, shape, dtype, order="C", allocator=None): """Returns an array of the given shape and dtype filled with 0's.""" - def _zeros(queue, shape, dtype, order="C", allocator=None): - result = Array(queue, shape, dtype, - order=order, allocator=allocator) - zero = np.zeros((), dtype) - result.fill(zero) - return result - - if isinstance(args[0], cl.Context): - from warnings import warn - warn("Passing a context as first argument is deprecated. " - "This will be continue to be accepted througout " - "versions 2011.x of PyOpenCL.", - DeprecationWarning, 2) - args = args[1:] - - return _zeros(*args, **kwargs) + result = Array(queue, shape, dtype, + order=order, allocator=allocator) + zero = np.zeros((), dtype) + result.fill(zero) + return result def empty_like(ary): return ary._new_with_changes(data=None) @@ -920,7 +912,15 @@ def _arange_knl(result, start, step): return elementwise.get_arange_kernel( result.context, result.dtype) -def _arange(queue, *args, **kwargs): +def arange(queue, *args, **kwargs): + """Create an array filled with numbers spaced `step` apart, + starting from `start` and ending at `stop`. + + For floating point arguments, the length of the result is + `ceil((stop - start)/step)`. This rule may result in the last + element of the result being greater than stop. + """ + # argument processing ----------------------------------------------------- # Yuck. Thanks, numpy developers. ;) @@ -992,28 +992,6 @@ def _arange(queue, *args, **kwargs): _arange_knl(result, start, step, queue=queue) return result - - - -def arange(*args, **kwargs): - """Create an array filled with numbers spaced `step` apart, - starting from `start` and ending at `stop`. - - For floating point arguments, the length of the result is - `ceil((stop - start)/step)`. This rule may result in the last - element of the result being greater than stop. - """ - - if isinstance(args[0], cl.Context): - from warnings import warn - warn("Passing a context as first argument is deprecated. " - "This will be continue to be accepted througout " - "versions 2011.x of PyOpenCL.", - DeprecationWarning, 2) - args = args[1:] - - return _arange(*args, **kwargs) - # }}} # {{{ take/put -- GitLab