From 56cd2bf152d44896e4255e18ad303b12b6817ef6 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 13 Nov 2018 21:30:17 -0600 Subject: [PATCH 1/7] ListOfListsBuilder: Add back support for MemoryObject arguments --- pyopencl/algorithm.py | 26 ++++++++++++++++++++++---- pyopencl/scan.py | 11 +++++++++-- pyopencl/tools.py | 12 ------------ test/test_algorithm.py | 25 +++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/pyopencl/algorithm.py b/pyopencl/algorithm.py index 92730750..eb581f39 100644 --- a/pyopencl/algorithm.py +++ b/pyopencl/algorithm.py @@ -1111,8 +1111,26 @@ class ListOfListsBuilder: if self.eliminate_empty_output_lists: compress_kernel = self.get_compress_kernel(index_dtype) - from pyopencl.tools import expand_runtime_arg_list - args = expand_runtime_arg_list(self.arg_decls, args) + data_args = [] + for i, (arg_descr, arg_val) in enumerate(zip(self.arg_decls, args)): + from pyopencl.tools import VectorArg + if isinstance(arg_descr, VectorArg): + from pyopencl import MemoryObject + if isinstance(arg_val, MemoryObject): + data_args.append(arg_val) + if arg_descr.with_offset: + raise ValueError( + "with_offset=True specified for argument '%d' " + "but the argument is not an array." % i) + + data_args.append(arg_val.base_data) + if arg_descr.with_offset: + data_args.append(arg_val.offset) + else: + data_args.append(arg_val) + + del args + data_args = tuple(data_args) # {{{ allocate memory for counts @@ -1151,7 +1169,7 @@ class ListOfListsBuilder: gsize, lsize = splay(queue, n_objects) count_event = count_kernel(queue, gsize, lsize, - *(tuple(count_list_args) + args + (n_objects,)), + *(tuple(count_list_args) + data_args + (n_objects,)), **dict(wait_for=wait_for)) compress_events = {} @@ -1257,7 +1275,7 @@ class ListOfListsBuilder: # }}} evt = write_kernel(queue, gsize, lsize, - *(tuple(write_list_args) + args + (n_objects,)), + *(tuple(write_list_args) + data_args + (n_objects,)), **dict(wait_for=scan_events)) return result, evt diff --git a/pyopencl/scan.py b/pyopencl/scan.py index 6218d571..cef68c67 100644 --- a/pyopencl/scan.py +++ b/pyopencl/scan.py @@ -1480,8 +1480,15 @@ class GenericScanKernel(_GenericScanKernelBase): # We're done here. (But pretend to return an event.) return cl.enqueue_marker(queue, wait_for=wait_for) - from pyopencl.tools import expand_runtime_arg_list - data_args = list(expand_runtime_arg_list(self.parsed_args, args)) + data_args = [] + for arg_descr, arg_val in zip(self.parsed_args, args): + from pyopencl.tools import VectorArg + if isinstance(arg_descr, VectorArg): + data_args.append(arg_val.base_data) + if arg_descr.with_offset: + data_args.append(arg_val.offset) + else: + data_args.append(arg_val) # }}} diff --git a/pyopencl/tools.py b/pyopencl/tools.py index b1dcf9f2..369fb272 100644 --- a/pyopencl/tools.py +++ b/pyopencl/tools.py @@ -400,18 +400,6 @@ def get_arg_offset_adjuster_code(arg_types): return "\n".join(result) - -def expand_runtime_arg_list(args, user_args): - data_args = [] - for arg_descr, arg_val in zip(args, user_args): - if isinstance(arg_descr, VectorArg): - data_args.append(arg_val.base_data) - if arg_descr.with_offset: - data_args.append(arg_val.offset) - else: - data_args.append(arg_val) - return tuple(data_args) - # }}} diff --git a/test/test_algorithm.py b/test/test_algorithm.py index 5c09b565..0360d6a3 100644 --- a/test/test_algorithm.py +++ b/test/test_algorithm.py @@ -880,6 +880,31 @@ def test_list_builder(ctx_factory): assert (inf.lists.get()[-6:] == [1, 2, 2, 3, 3, 3]).all() +def test_list_builder_with_memoryobject(ctx_factory): + from pytest import importorskip + importorskip("mako") + + context = ctx_factory() + queue = cl.CommandQueue(context) + + from pyopencl.algorithm import ListOfListsBuilder + from pyopencl.tools import VectorArg + builder = ListOfListsBuilder(context, [("mylist", np.int32)], """//CL// + void generate(LIST_ARG_DECL USER_ARG_DECL index_type i) + { + APPEND_mylist(input_list[i]); + } + """, arg_decls=[VectorArg(float, "input_list")]) + + n = 10000 + input_list = cl.array.zeros(queue, (n,), float) + result, evt = builder(queue, n, input_list.data) + + inf = result["mylist"] + assert inf.count == n + assert (inf.lists.get() == 0).all() + + def test_list_builder_with_offset(ctx_factory): from pytest import importorskip importorskip("mako") -- GitLab From e6ba51c0514be9129fb396668f077e6d3911a3ad Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 13 Nov 2018 22:34:08 -0500 Subject: [PATCH 2/7] Fix control flow --- pyopencl/algorithm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyopencl/algorithm.py b/pyopencl/algorithm.py index eb581f39..513e5ad8 100644 --- a/pyopencl/algorithm.py +++ b/pyopencl/algorithm.py @@ -1122,6 +1122,7 @@ class ListOfListsBuilder: raise ValueError( "with_offset=True specified for argument '%d' " "but the argument is not an array." % i) + continue data_args.append(arg_val.base_data) if arg_descr.with_offset: -- GitLab From e2495c60b06947a5d0e567cdbc48091ecaba1974 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 13 Nov 2018 22:08:12 -0600 Subject: [PATCH 3/7] Update docs to state that we allow arrays or memoryobjects. --- pyopencl/algorithm.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyopencl/algorithm.py b/pyopencl/algorithm.py index 513e5ad8..a5576796 100644 --- a/pyopencl/algorithm.py +++ b/pyopencl/algorithm.py @@ -1042,8 +1042,8 @@ class ListOfListsBuilder: def __call__(self, queue, n_objects, *args, **kwargs): """ :arg args: arguments corresponding to arg_decls in the constructor. - :class:`pyopencl.array.Array` are not allowed directly and should - be passed as their :attr:`pyopencl.array.Array.data` attribute instead. + Arguments must be either 1D :class:`pyopencl.array.Array' objects + or :class:`pyopencl.MemoryObject' objects. :arg allocator: optionally, the allocator to use to allocate new arrays. :arg omit_lists: An iterable of list names that should *not* be built @@ -1124,6 +1124,9 @@ class ListOfListsBuilder: "but the argument is not an array." % i) continue + if arg_val.ndim != 1: + raise ValueError("Only 1D arrays supported") + data_args.append(arg_val.base_data) if arg_descr.with_offset: data_args.append(arg_val.offset) -- GitLab From d1828b83fa16ce07ce48e456a65aa1e4d42856cd Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 13 Nov 2018 23:12:37 -0500 Subject: [PATCH 4/7] Fix markup --- pyopencl/algorithm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyopencl/algorithm.py b/pyopencl/algorithm.py index a5576796..5a878099 100644 --- a/pyopencl/algorithm.py +++ b/pyopencl/algorithm.py @@ -1042,8 +1042,8 @@ class ListOfListsBuilder: def __call__(self, queue, n_objects, *args, **kwargs): """ :arg args: arguments corresponding to arg_decls in the constructor. - Arguments must be either 1D :class:`pyopencl.array.Array' objects - or :class:`pyopencl.MemoryObject' objects. + Arguments must be either 1D :class:`pyopencl.array.Array` objects + or :class:`pyopencl.MemoryObject` objects. :arg allocator: optionally, the allocator to use to allocate new arrays. :arg omit_lists: An iterable of list names that should *not* be built -- GitLab From 4b69c5eed80085181c45d9cfb90ea79ecc133bf0 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Tue, 13 Nov 2018 22:27:28 -0600 Subject: [PATCH 5/7] More useful error messages --- pyopencl/algorithm.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyopencl/algorithm.py b/pyopencl/algorithm.py index a5576796..413af08e 100644 --- a/pyopencl/algorithm.py +++ b/pyopencl/algorithm.py @@ -1120,12 +1120,12 @@ class ListOfListsBuilder: data_args.append(arg_val) if arg_descr.with_offset: raise ValueError( - "with_offset=True specified for argument '%d' " - "but the argument is not an array." % i) + "with_offset=True specified for argument %d " + "but the argument is not an array" % i) continue if arg_val.ndim != 1: - raise ValueError("Only 1D arrays supported") + raise ValueError("argument %d is a multidimensional array" % i) data_args.append(arg_val.base_data) if arg_descr.with_offset: -- GitLab From 736f75371d9659d5b5432212f95c09de29d3fbb6 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Wed, 14 Nov 2018 04:17:09 -0500 Subject: [PATCH 6/7] Fix documentation --- pyopencl/algorithm.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyopencl/algorithm.py b/pyopencl/algorithm.py index c8fc5869..9713db39 100644 --- a/pyopencl/algorithm.py +++ b/pyopencl/algorithm.py @@ -1042,8 +1042,11 @@ class ListOfListsBuilder: def __call__(self, queue, n_objects, *args, **kwargs): """ :arg args: arguments corresponding to arg_decls in the constructor. - Arguments must be either 1D :class:`pyopencl.array.Array` objects - or :class:`pyopencl.MemoryObject` objects. + Array-like arguments must be either + 1D :class:`pyopencl.array.Array` objects or + :class:`pyopencl.MemoryObject` objects, the latter of which + can be obtained from a :class:`pyopencl.array.Array` using the + :attr:`pyopencl.array.Array.data` attribute. :arg allocator: optionally, the allocator to use to allocate new arrays. :arg omit_lists: An iterable of list names that should *not* be built -- GitLab From 9f00c62106c36a149715bcd792f58a5bc1937f4d Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Wed, 14 Nov 2018 04:26:15 -0500 Subject: [PATCH 7/7] Grammar --- pyopencl/algorithm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyopencl/algorithm.py b/pyopencl/algorithm.py index 9713db39..dfa5d4bb 100644 --- a/pyopencl/algorithm.py +++ b/pyopencl/algorithm.py @@ -1044,7 +1044,7 @@ class ListOfListsBuilder: :arg args: arguments corresponding to arg_decls in the constructor. Array-like arguments must be either 1D :class:`pyopencl.array.Array` objects or - :class:`pyopencl.MemoryObject` objects, the latter of which + :class:`pyopencl.MemoryObject` objects, of which the latter can be obtained from a :class:`pyopencl.array.Array` using the :attr:`pyopencl.array.Array.data` attribute. :arg allocator: optionally, the allocator to use to allocate new -- GitLab