From 282896e34203541d588d7bba0adbd716e82c4d96 Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 12:31:55 -0500 Subject: [PATCH 01/15] enable reduction on integers --- loopy/library/reduction.py | 28 +++++++++++++++++++++++++++- loopy/target/opencl.py | 4 ++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/loopy/library/reduction.py b/loopy/library/reduction.py index f435820b2..c61c052c0 100644 --- a/loopy/library/reduction.py +++ b/loopy/library/reduction.py @@ -135,13 +135,37 @@ def get_le_neutral(dtype): if dtype.numpy_dtype.kind == "f": # OpenCL 1.1, section 6.11.2 return var("INFINITY") + elif dtype.numpy_dtype.kind == "i": + if dtype.numpy_dtype.itemsize == 4: + #32 bit integer + return var("INT_MAX") + elif dtype.numpy_dtype.itemsize == 8: + #64 bit integer + return var('LONG_MAX') else: raise NotImplementedError("less") +def get_ge_neutral(dtype): + """Return a number y that satisfies (x >= y) for all y.""" + + if dtype.numpy_dtype.kind == "f": + # OpenCL 1.1, section 6.11.2 + return -var("INFINITY") + elif dtype.numpy_dtype.kind == "i": + if dtype.numpy_dtype.itemsize == 4: + #32 bit integer + return var("INT_MIN") + elif dtype.numpy_dtype.itemsize == 8: + #64 bit integer + return var('LONG_MIN') + else: + raise NotImplementedError("less") + + class MaxReductionOperation(ScalarReductionOperation): def neutral_element(self, dtype, inames): - return -get_le_neutral(dtype) + return get_ge_neutral(dtype) def __call__(self, dtype, operand1, operand2, inames): return var("max")(operand1, operand2) @@ -213,6 +237,8 @@ def get_argext_preamble(kernel, func_id): c_code_mapper = CCodeMapper() + neutral = get_ge_neutral if op.neutral_sign < 0 else get_le_neutral + return (prefix, """ inline %(scalar_t)s %(prefix)s_init(%(index_t)s *index_out) { diff --git a/loopy/target/opencl.py b/loopy/target/opencl.py index 31cf7c6b6..01e56405e 100644 --- a/loopy/target/opencl.py +++ b/loopy/target/opencl.py @@ -249,6 +249,10 @@ def opencl_symbol_mangler(kernel, name): return NumpyType(np.dtype(np.float64)), name elif name == "INFINITY": return NumpyType(np.dtype(np.float32)), name + elif name.startswith("INT_"): + return NumpyType(np.dtype(np.int32)), name + elif name.startswith("LONG_"): + return NumpyType(np.dtype(np.int64)), name else: return None -- GitLab From 05d3ca9bc3e1ceeb4aebb6bf514bfb4ad3a7f192 Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 13:06:33 -0500 Subject: [PATCH 02/15] add integer reduction tests --- test/test_loopy.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/test_loopy.py b/test/test_loopy.py index 9eaece6a8..2438829f4 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1933,6 +1933,37 @@ def test_unscheduled_insn_detection(): lp.generate_code(knl) +def test_integer_reduction(): + n = 200 + var_int = np.random.randint(1000, size=n, dtype=np.int32) + var_lp = lp.TemporaryVariable('var', initializer=var_int, + scope=scopes.PRIVATE, + read_only=True, + dtype=np.int32, + shape=lp.auto) + + reductions = [('max', lambda x: x == np.max(var_int)), + ('min', lambda x: x == np.min(var_int)), + ('sum', lambda x: x == np.sum(var_int)), + ('product', lambda x: x == np.prod(var_int)), + ('argmax', lambda x: (x[0] == np.max(var_int) and + x[1] == np.argmax(var_int))), + ('argmin', lambda x: (x[0] == np.min(var_int) and + x[1] == np.argmin(var_int)))] + + for reduction, function in reductions: + kstr = (("out" if not 'arg' in reduction + else "out[0], out[1]") + ' = {}(k, var[k])'.format(reduction)) + knl = lp.make_kernel('{[k]: 0<=k 1: exec(sys.argv[1]) -- GitLab From 628526e79c769b8779df4a6af96360c33cde9d32 Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 13:07:35 -0500 Subject: [PATCH 03/15] add integer reduction tests --- test/test_loopy.py | 57 +++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/test/test_loopy.py b/test/test_loopy.py index 2438829f4..579215092 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1935,34 +1935,35 @@ def test_unscheduled_insn_detection(): def test_integer_reduction(): n = 200 - var_int = np.random.randint(1000, size=n, dtype=np.int32) - var_lp = lp.TemporaryVariable('var', initializer=var_int, - scope=scopes.PRIVATE, - read_only=True, - dtype=np.int32, - shape=lp.auto) - - reductions = [('max', lambda x: x == np.max(var_int)), - ('min', lambda x: x == np.min(var_int)), - ('sum', lambda x: x == np.sum(var_int)), - ('product', lambda x: x == np.prod(var_int)), - ('argmax', lambda x: (x[0] == np.max(var_int) and - x[1] == np.argmax(var_int))), - ('argmin', lambda x: (x[0] == np.min(var_int) and - x[1] == np.argmin(var_int)))] - - for reduction, function in reductions: - kstr = (("out" if not 'arg' in reduction - else "out[0], out[1]") + ' = {}(k, var[k])'.format(reduction)) - knl = lp.make_kernel('{[k]: 0<=k 1: -- GitLab From 9c9a83bf4d6a2301ddb3531ca070476aec668653 Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 13:13:04 -0500 Subject: [PATCH 04/15] fix neutral mapping to use new methods --- loopy/library/reduction.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/loopy/library/reduction.py b/loopy/library/reduction.py index c61c052c0..66e94ac62 100644 --- a/loopy/library/reduction.py +++ b/loopy/library/reduction.py @@ -266,8 +266,7 @@ def get_argext_preamble(kernel, func_id): scalar_t=kernel.target.dtype_to_typename(func_id.scalar_dtype), prefix=prefix, index_t=kernel.target.dtype_to_typename(kernel.index_dtype), - neutral=c_code_mapper( - op.neutral_sign*get_le_neutral(func_id.scalar_dtype)), + neutral=c_code_mapper(neutral(func_id.scalar_dtype)), comp=op.update_comparison, )) -- GitLab From f03f874db9b08a6bef9bfc73dd5090a247b4df9c Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 13:14:51 -0500 Subject: [PATCH 05/15] correct test context --- test/test_loopy.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_loopy.py b/test/test_loopy.py index 579215092..5a7c28cac 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1934,6 +1934,9 @@ def test_unscheduled_insn_detection(): def test_integer_reduction(): + ctx = ctx_factory() + queue = cl.CommandQueue(ctx) + n = 200 for vtype in [np.int32, np.int64]: var_int = np.random.randint(1000, size=n, dtype=vtype) -- GitLab From 103fafe08e6997828886c4c961ebb0e37f7f7a9f Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 13:21:29 -0500 Subject: [PATCH 06/15] add scope import to fix test --- test/test_loopy.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test_loopy.py b/test/test_loopy.py index 5a7c28cac..0eeaba536 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1937,12 +1937,14 @@ def test_integer_reduction(): ctx = ctx_factory() queue = cl.CommandQueue(ctx) + from loopy.kernel.data import temp_var_scope as scopes + n = 200 for vtype in [np.int32, np.int64]: var_int = np.random.randint(1000, size=n, dtype=vtype) var_lp = lp.TemporaryVariable('var', initializer=var_int, - scope=scopes.PRIVATE, read_only=True, + scopes=scopes.PRIVATE, dtype=vtype, shape=lp.auto) -- GitLab From 128aa58131657d52bb67ff4faa3c5b236e9bb28a Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 13:22:44 -0500 Subject: [PATCH 07/15] minor PEP8 fixes --- test/test_loopy.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_loopy.py b/test/test_loopy.py index 0eeaba536..63ef3410d 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1958,7 +1958,7 @@ def test_integer_reduction(): x[1] == np.argmin(var_int)))] for reduction, function in reductions: - kstr = (("out" if not 'arg' in reduction + kstr = (("out" if 'arg' not in reduction else "out[0], out[1]") + ' = {}(k, var[k])'.format(reduction)) knl = lp.make_kernel('{[k]: 0<=k 1: exec(sys.argv[1]) -- GitLab From ae767f0e6f837e2d72906bbf4da83751f6a50e51 Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 13:24:26 -0500 Subject: [PATCH 08/15] more (hopefully final -.-) minor fixes --- loopy/library/reduction.py | 2 +- test/test_loopy.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/loopy/library/reduction.py b/loopy/library/reduction.py index 66e94ac62..6ea57cb47 100644 --- a/loopy/library/reduction.py +++ b/loopy/library/reduction.py @@ -145,6 +145,7 @@ def get_le_neutral(dtype): else: raise NotImplementedError("less") + def get_ge_neutral(dtype): """Return a number y that satisfies (x >= y) for all y.""" @@ -162,7 +163,6 @@ def get_ge_neutral(dtype): raise NotImplementedError("less") - class MaxReductionOperation(ScalarReductionOperation): def neutral_element(self, dtype, inames): return get_ge_neutral(dtype) diff --git a/test/test_loopy.py b/test/test_loopy.py index 63ef3410d..34a232beb 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1933,7 +1933,7 @@ def test_unscheduled_insn_detection(): lp.generate_code(knl) -def test_integer_reduction(): +def test_integer_reduction(ctx_factory): ctx = ctx_factory() queue = cl.CommandQueue(ctx) -- GitLab From da770deb5ec3615b9af8b2efed4c09f5b3d2a1d2 Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 14:07:41 -0500 Subject: [PATCH 09/15] final test fix --- test/test_loopy.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_loopy.py b/test/test_loopy.py index 34a232beb..f4696236d 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1938,14 +1938,15 @@ def test_integer_reduction(ctx_factory): queue = cl.CommandQueue(ctx) from loopy.kernel.data import temp_var_scope as scopes + from loopy.types import to_loopy_type n = 200 for vtype in [np.int32, np.int64]: var_int = np.random.randint(1000, size=n, dtype=vtype) var_lp = lp.TemporaryVariable('var', initializer=var_int, read_only=True, - scopes=scopes.PRIVATE, - dtype=vtype, + scope=scopes.PRIVATE, + dtype=to_loopy_type(vtype), shape=lp.auto) reductions = [('max', lambda x: x == np.max(var_int)), -- GitLab From c20854bfb3e03b410f2d3abc27d10d0a5f640094 Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 14:41:04 -0500 Subject: [PATCH 10/15] check that the index returned is a minimum, rather than the exact value from numpy (in case of duplicate min/maxs) --- test/test_loopy.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_loopy.py b/test/test_loopy.py index f4696236d..ed35251e0 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1954,9 +1954,9 @@ def test_integer_reduction(ctx_factory): ('sum', lambda x: x == np.sum(var_int)), ('product', lambda x: x == np.prod(var_int)), ('argmax', lambda x: (x[0] == np.max(var_int) and - x[1] == np.argmax(var_int))), + var_int[out[1]] == np.max(var_int))), ('argmin', lambda x: (x[0] == np.min(var_int) and - x[1] == np.argmin(var_int)))] + var_int[out[1]] == np.min(var_int)))] for reduction, function in reductions: kstr = (("out" if 'arg' not in reduction @@ -1967,7 +1967,7 @@ def test_integer_reduction(ctx_factory): knl = lp.fix_parameters(knl, n=200) - _, (out,) = knl(queue) + _, (out,) = knl(queue, out_host=True) assert function(out) -- GitLab From bd3bb3962b190fcf5ac3ec33f81f768985f46fe5 Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 14:54:18 -0500 Subject: [PATCH 11/15] old numpy compatibility --- test/test_loopy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_loopy.py b/test/test_loopy.py index ed35251e0..8c46e52d7 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1942,7 +1942,7 @@ def test_integer_reduction(ctx_factory): n = 200 for vtype in [np.int32, np.int64]: - var_int = np.random.randint(1000, size=n, dtype=vtype) + var_int = np.random.randint(1000, size=n).astype(vtype) var_lp = lp.TemporaryVariable('var', initializer=var_int, read_only=True, scope=scopes.PRIVATE, -- GitLab From 4918d298aa3784a860d639a05dbdb4f7402e3e23 Mon Sep 17 00:00:00 2001 From: arghdos Date: Fri, 9 Dec 2016 16:11:49 -0500 Subject: [PATCH 12/15] more python2.6 compat --- test/test_loopy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_loopy.py b/test/test_loopy.py index 8c46e52d7..c43e06a8c 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1960,8 +1960,8 @@ def test_integer_reduction(ctx_factory): for reduction, function in reductions: kstr = (("out" if 'arg' not in reduction - else "out[0], out[1]") + ' = {}(k, var[k])'.format(reduction)) - knl = lp.make_kernel('{[k]: 0<=k Date: Fri, 9 Dec 2016 16:13:42 -0500 Subject: [PATCH 13/15] another try --- test/test_loopy.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_loopy.py b/test/test_loopy.py index c43e06a8c..e41d55b85 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -1959,8 +1959,9 @@ def test_integer_reduction(ctx_factory): var_int[out[1]] == np.min(var_int)))] for reduction, function in reductions: - kstr = (("out" if 'arg' not in reduction - else "out[0], out[1]") + ' = %s(k, var[k])' % reduction)` + kstr = ("out" if 'arg' not in reduction + else "out[0], out[1]") + kstr += ' = {0}(k, var[k])'.format(reduction) knl = lp.make_kernel('{[k]: 0<=k Date: Sat, 10 Dec 2016 11:36:11 -0500 Subject: [PATCH 14/15] add opencl ref --- loopy/library/reduction.py | 1 + 1 file changed, 1 insertion(+) diff --git a/loopy/library/reduction.py b/loopy/library/reduction.py index 6ea57cb47..8eaf4ac38 100644 --- a/loopy/library/reduction.py +++ b/loopy/library/reduction.py @@ -136,6 +136,7 @@ def get_le_neutral(dtype): # OpenCL 1.1, section 6.11.2 return var("INFINITY") elif dtype.numpy_dtype.kind == "i": + # OpenCL 1.1, section 6.11.3 if dtype.numpy_dtype.itemsize == 4: #32 bit integer return var("INT_MAX") -- GitLab From 922d51719ada2e829eaeb78f3b2cfad2c653529c Mon Sep 17 00:00:00 2001 From: arghdos Date: Sat, 10 Dec 2016 11:44:17 -0500 Subject: [PATCH 15/15] oops, add the section reference here too --- loopy/library/reduction.py | 1 + 1 file changed, 1 insertion(+) diff --git a/loopy/library/reduction.py b/loopy/library/reduction.py index 8eaf4ac38..d24b61c12 100644 --- a/loopy/library/reduction.py +++ b/loopy/library/reduction.py @@ -154,6 +154,7 @@ def get_ge_neutral(dtype): # OpenCL 1.1, section 6.11.2 return -var("INFINITY") elif dtype.numpy_dtype.kind == "i": + # OpenCL 1.1, section 6.11.3 if dtype.numpy_dtype.itemsize == 4: #32 bit integer return var("INT_MIN") -- GitLab