From 6743c619235929f669a6b4a868043f177a45f8f2 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Sat, 24 Aug 2019 04:21:24 +0530 Subject: [PATCH 1/7] starts with the fix --- loopy/target/c/codegen/expression.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/loopy/target/c/codegen/expression.py b/loopy/target/c/codegen/expression.py index a6742c225..464644d58 100644 --- a/loopy/target/c/codegen/expression.py +++ b/loopy/target/c/codegen/expression.py @@ -120,6 +120,7 @@ class ExpressionToCExpressionMapper(IdentityMapper): # }}} def map_variable(self, expr, type_context): + # KK FIXME: See my note in map_constant def postproc(x): return x @@ -359,6 +360,11 @@ class ExpressionToCExpressionMapper(IdentityMapper): return cast(self.rec(expr.child, type_context)) def map_constant(self, expr, type_context): + #KK FIXME + # Here type context is not followed correctly, + # if I give map_constant(self, 2, 'f'0) + # it does not force it to a float. + # there is a similar problem in map_variable from loopy.symbolic import Literal if isinstance(expr, (complex, np.complexfloating)): @@ -697,9 +703,14 @@ class ExpressionToCExpressionMapper(IdentityMapper): elif is_zero(expr.exponent - 2): return self.rec(expr.base*expr.base, type_context) - return type(expr)( - self.rec(expr.base, type_context), - self.rec(expr.exponent, type_context)) + if type_context == 'i': + return var("(int)")(type(expr)( + self.rec(1.0*expr.base, 'f'), + self.rec(1.0*expr.exponent, 'f'))+0.5) + else: + return type(expr)( + self.rec(expr.base, type_context), + self.rec(expr.exponent, type_context)) if not self.allow_complex: return base_impl(expr, type_context) -- GitLab From 07b992da7dcce19b7439b58c918ddbd527625729 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Tue, 27 Aug 2019 18:24:50 -0500 Subject: [PATCH 2/7] adds map_literal in dep_mapper --- loopy/symbolic.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/loopy/symbolic.py b/loopy/symbolic.py index 8f5337533..7b0897727 100644 --- a/loopy/symbolic.py +++ b/loopy/symbolic.py @@ -317,6 +317,9 @@ class DependencyMapper(DependencyMapperBase): def map_type_cast(self, expr, *args, **kwargs): return self.rec(expr.child, *args, **kwargs) + def map_literal(self, expr, *args, **kwargs): + return set() + class SubstitutionRuleExpander(IdentityMapper): def __init__(self, rules): -- GitLab From a6964445d661b9f354e3dcc0d196445cc83fff55 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Tue, 27 Aug 2019 18:26:47 -0500 Subject: [PATCH 3/7] post processing for variables with non-matching types --- loopy/target/c/codegen/expression.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/loopy/target/c/codegen/expression.py b/loopy/target/c/codegen/expression.py index 464644d58..9628f70e1 100644 --- a/loopy/target/c/codegen/expression.py +++ b/loopy/target/c/codegen/expression.py @@ -120,8 +120,14 @@ class ExpressionToCExpressionMapper(IdentityMapper): # }}} def map_variable(self, expr, type_context): - # KK FIXME: See my note in map_constant def postproc(x): + if type_context != self.infer_type(x).numpy_dtype.kind: + kind_to_c_type = { + 'i': "(int)", + 'f': "(float)", + 'd': "(double)"} + return var(kind_to_c_type[type_context])(x) + return x if expr.name in self.codegen_state.var_subst_map: @@ -360,11 +366,6 @@ class ExpressionToCExpressionMapper(IdentityMapper): return cast(self.rec(expr.child, type_context)) def map_constant(self, expr, type_context): - #KK FIXME - # Here type context is not followed correctly, - # if I give map_constant(self, 2, 'f'0) - # it does not force it to a float. - # there is a similar problem in map_variable from loopy.symbolic import Literal if isinstance(expr, (complex, np.complexfloating)): @@ -705,8 +706,8 @@ class ExpressionToCExpressionMapper(IdentityMapper): if type_context == 'i': return var("(int)")(type(expr)( - self.rec(1.0*expr.base, 'f'), - self.rec(1.0*expr.exponent, 'f'))+0.5) + self.rec(expr.base, 'f'), + self.rec(expr.exponent, 'f'))+0.5) else: return type(expr)( self.rec(expr.base, type_context), -- GitLab From eed8e167229512e372f7a364237d3db361cae21a Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Tue, 27 Aug 2019 18:27:01 -0500 Subject: [PATCH 4/7] adds test for integer power --- test/test_loopy.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/test_loopy.py b/test/test_loopy.py index d506258c2..e3fe54a65 100644 --- a/test/test_loopy.py +++ b/test/test_loopy.py @@ -3028,6 +3028,30 @@ def test_non_integral_array_idx_raises(): print(lp.generate_code_v2(knl).device_code()) +def test_ipow(ctx_factory): + knl = lp.make_kernel( + "{[i, j]: 0<=i<=4 and 0<=j<16}", + """ + out[j] = 0 {id=init} + out[i] = a[2**i-1] {dep=init} + """, [lp.GlobalArg('a', np.float64), '...']) + + a = np.random.randn(16) + expected_out = np.zeros(16) + + knl = lp.set_options(knl, 'write_cl') + + for i in range(5): + expected_out[i] = a[2**i-1] + + ctx = ctx_factory() + queue = cl.CommandQueue(ctx) + + evt, (out, ) = knl(queue, a=a) + + assert np.allclose(out, expected_out) + + if __name__ == "__main__": if len(sys.argv) > 1: exec(sys.argv[1]) -- GitLab From cbf839d78349833f6b02bfe9158c7759dde2f7fa Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Wed, 28 Aug 2019 11:12:22 -0500 Subject: [PATCH 5/7] adds support for pown --- loopy/target/opencl.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/loopy/target/opencl.py b/loopy/target/opencl.py index 8a6e52842..8f153336c 100644 --- a/loopy/target/opencl.py +++ b/loopy/target/opencl.py @@ -299,6 +299,24 @@ class ExpressionToOpenCLCExpressionMapper(ExpressionToCExpressionMapper): def map_local_hw_index(self, expr, type_context): return var("lid")(expr.axis) + def map_power(self, expr, type_context): + if self.infer_type(expr.exponent).is_integral() and not ( + self.infer_type(expr.base).is_complex()): + # opencl provides special implementation for int exponents + base_kind = 'f' if self.infer_type(expr.base).is_integral() else ( + None) + if type_context == 'i': + return var("(int)")(var("pown")( + self.rec(expr.base, base_kind), + self.rec(expr.exponent))+0.5) + else: + return var("pown")( + self.rec(expr.base, base_kind), + self.rec(expr.exponent)) + + return super(ExpressionToOpenCLCExpressionMapper, self).map_power(expr, + type_context) + # }}} -- GitLab From fc78c3429d3ad89e71fde8076f26be0ab96f4497 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Wed, 28 Aug 2019 11:14:53 -0500 Subject: [PATCH 6/7] account for type which we have not hand coded --- loopy/target/c/codegen/expression.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/loopy/target/c/codegen/expression.py b/loopy/target/c/codegen/expression.py index 9628f70e1..98602a00a 100644 --- a/loopy/target/c/codegen/expression.py +++ b/loopy/target/c/codegen/expression.py @@ -121,11 +121,15 @@ class ExpressionToCExpressionMapper(IdentityMapper): def map_variable(self, expr, type_context): def postproc(x): - if type_context != self.infer_type(x).numpy_dtype.kind: - kind_to_c_type = { - 'i': "(int)", - 'f': "(float)", - 'd': "(double)"} + kind_to_c_type = { + 'i': "(int)", + 'f': "(float)", + 'd': "(double)"} + # FIXME: the second condition is for handling type_context not in + # our dict, to account for some dtype kinds which we have missed, + # like "None". Is this fine? + if type_context != self.infer_type(x).numpy_dtype.kind and ( + type_context in kind_to_c_type): return var(kind_to_c_type[type_context])(x) return x -- GitLab From 36ec19e4df90cccdfc29e12ee28eeeb3935f2808 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Wed, 28 Aug 2019 11:15:27 -0500 Subject: [PATCH 7/7] in C the upgrading of types is automatic --- loopy/target/c/codegen/expression.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/loopy/target/c/codegen/expression.py b/loopy/target/c/codegen/expression.py index 98602a00a..082f6a452 100644 --- a/loopy/target/c/codegen/expression.py +++ b/loopy/target/c/codegen/expression.py @@ -709,13 +709,14 @@ class ExpressionToCExpressionMapper(IdentityMapper): return self.rec(expr.base*expr.base, type_context) if type_context == 'i': + # add 0.5 and then casting to int to mimic rounding return var("(int)")(type(expr)( - self.rec(expr.base, 'f'), - self.rec(expr.exponent, 'f'))+0.5) + self.rec(expr.base), + self.rec(expr.exponent))+0.5) else: return type(expr)( - self.rec(expr.base, type_context), - self.rec(expr.exponent, type_context)) + self.rec(expr.base), + self.rec(expr.exponent)) if not self.allow_complex: return base_impl(expr, type_context) -- GitLab