[pypy-commit] pypy numpy-single-jitdriver: some fixes

fijal noreply at buildbot.pypy.org
Fri Feb 3 11:03:30 CET 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: numpy-single-jitdriver
Changeset: r52050:16f093b4c8be
Date: 2012-02-03 12:03 +0200
http://bitbucket.org/pypy/pypy/changeset/16f093b4c8be/

Log:	some fixes

diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -3,7 +3,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.module.micronumpy import (interp_ufuncs, interp_dtype, interp_boxes,
-    signature, support)
+    signature, support, loop)
 from pypy.module.micronumpy.strides import (calculate_slice_strides,
     shape_agreement, find_shape_and_elems, get_shape_from_iterable,
     calc_new_strides, to_coords)
@@ -17,20 +17,6 @@
 from pypy.module.micronumpy.appbridge import get_appbridge_cache
 
 
-all_driver = jit.JitDriver(
-    greens=['shapelen', 'sig'],
-    virtualizables=['frame'],
-    reds=['frame', 'self', 'dtype'],
-    get_printable_location=signature.new_printable_location('all'),
-    name='numpy_all',
-)
-any_driver = jit.JitDriver(
-    greens=['shapelen', 'sig'],
-    virtualizables=['frame'],
-    reds=['frame', 'self', 'dtype'],
-    get_printable_location=signature.new_printable_location('any'),
-    name='numpy_any',
-)
 slice_driver = jit.JitDriver(
     greens=['shapelen', 'sig'],
     virtualizables=['frame'],
@@ -166,6 +152,8 @@
     descr_prod = _reduce_ufunc_impl("multiply", True)
     descr_max = _reduce_ufunc_impl("maximum")
     descr_min = _reduce_ufunc_impl("minimum")
+    descr_all = _reduce_ufunc_impl('logical_and')
+    descr_any = _reduce_ufunc_impl('logical_or')
 
     def _reduce_argmax_argmin_impl(op_name):
         reduce_driver = jit.JitDriver(
@@ -205,40 +193,6 @@
             return space.wrap(loop(self))
         return func_with_new_name(impl, "reduce_arg%s_impl" % op_name)
 
-    def _all(self):
-        dtype = self.find_dtype()
-        sig = self.find_sig()
-        frame = sig.create_frame(self)
-        shapelen = len(self.shape)
-        while not frame.done():
-            all_driver.jit_merge_point(sig=sig,
-                                       shapelen=shapelen, self=self,
-                                       dtype=dtype, frame=frame)
-            if not dtype.itemtype.bool(sig.eval(frame, self)):
-                return False
-            frame.next(shapelen)
-        return True
-
-    def descr_all(self, space):
-        return space.wrap(self._all())
-
-    def _any(self):
-        dtype = self.find_dtype()
-        sig = self.find_sig()
-        frame = sig.create_frame(self)
-        shapelen = len(self.shape)
-        while not frame.done():
-            any_driver.jit_merge_point(sig=sig, frame=frame,
-                                       shapelen=shapelen, self=self,
-                                       dtype=dtype)
-            if dtype.itemtype.bool(sig.eval(frame, self)):
-                return True
-            frame.next(shapelen)
-        return False
-
-    def descr_any(self, space):
-        return space.wrap(self._any())
-
     descr_argmax = _reduce_argmax_argmin_impl("max")
     descr_argmin = _reduce_argmax_argmin_impl("min")
 
@@ -746,7 +700,6 @@
         raise NotImplementedError
 
     def compute(self):
-        from pypy.module.micronumpy import loop
         ra = ResultArray(self, self.size, self.shape, self.res_dtype)
         loop.compute(ra)
         return ra.left
@@ -859,6 +812,12 @@
         return signature.ResultSignature(self.res_dtype, self.left.create_sig(),
                                          self.right.create_sig())
 
+def done_if_true(dtype, val):
+    return dtype.itemtype.bool(val)
+
+def done_if_false(dtype, val):
+    return not dtype.itemtype.bool(val)
+
 class ReduceArray(Call2):
     def __init__(self, func, name, identity, child, dtype):
         self.identity = identity
@@ -874,9 +833,15 @@
             frame.cur_value = self.identity.convert_to(self.calc_dtype)
     
     def create_sig(self):
+        if self.name == 'logical_and':
+            done_func = done_if_false
+        elif self.name == 'logical_or':
+            done_func = done_if_true
+        else:
+            done_func = None
         return signature.ReduceSignature(self.ufunc, self.name, self.res_dtype,
                                  signature.ScalarSignature(self.res_dtype),
-                                         self.right.create_sig())
+                                         self.right.create_sig(), done_func)
 
 class AxisReduce(Call2):
     _immutable_fields_ = ['left', 'right']
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import interp2app, unwrap_spec, NoneNotWrapped
 from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
-from pypy.module.micronumpy import interp_boxes, interp_dtype, support
+from pypy.module.micronumpy import interp_boxes, interp_dtype, support, loop
 from pypy.rlib.rarithmetic import LONG_BIT
 from pypy.tool.sourcetools import func_with_new_name
 
@@ -120,8 +120,6 @@
                keepdims=False):
         from pypy.module.micronumpy.interp_numarray import convert_to_array, \
                                                            Scalar, ReduceArray
-        from pypy.module.micronumpy import loop
-        
         if self.argcount != 2:
             raise OperationError(space.w_ValueError, space.wrap("reduce only "
                 "supported for binary functions"))
@@ -132,14 +130,16 @@
         if isinstance(obj, Scalar):
             raise OperationError(space.w_TypeError, space.wrap("cannot reduce "
                 "on a scalar"))
-
         size = obj.size
-        dtype = find_unaryop_result_dtype(
-            space, obj.find_dtype(),
-            promote_to_float=self.promote_to_float,
-            promote_to_largest=promote_to_largest,
-            promote_bools=True
-        )
+        if self.comparison_func:
+            dtype = interp_dtype.get_dtype_cache(space).w_booldtype
+        else:
+            dtype = find_unaryop_result_dtype(
+                space, obj.find_dtype(),
+                promote_to_float=self.promote_to_float,
+                promote_to_largest=promote_to_largest,
+                promote_bools=True
+            )
         shapelen = len(obj.shape)
         if self.identity is None and size == 0:
             raise operationerrfmt(space.w_ValueError, "zero-size array to "
@@ -152,8 +152,6 @@
     def do_axis_reduce(self, obj, dtype, dim, keepdims):
         from pypy.module.micronumpy.interp_numarray import AxisReduce,\
              W_NDimArray
-        from pypy.module.micronumpy import loop
-
         if keepdims:
             shape = obj.shape[:dim] + [1] + obj.shape[dim + 1:]
         else:
@@ -234,7 +232,6 @@
                 w_lhs.value.convert_to(calc_dtype),
                 w_rhs.value.convert_to(calc_dtype)
             ))
-
         new_shape = shape_agreement(space, w_lhs.shape, w_rhs.shape)
         w_res = Call2(self.func, self.name,
                       new_shape, calc_dtype,
@@ -404,8 +401,10 @@
             ("isnan", "isnan", 1, {"bool_result": True}),
             ("isinf", "isinf", 1, {"bool_result": True}),
 
-            ('logical_and', 'logical_and', 2, {'comparison_func': True}),
-            ('logical_or', 'logical_or', 2, {'comparison_func': True}),
+            ('logical_and', 'logical_and', 2, {'comparison_func': True,
+                                               'identity': 1}),
+            ('logical_or', 'logical_or', 2, {'comparison_func': True,
+                                             'identity': 0}),
             ('logical_xor', 'logical_xor', 2, {'comparison_func': True}),
             ('logical_not', 'logical_not', 1, {'bool_result': True}),
 
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -4,7 +4,6 @@
 """
 
 from pypy.rlib.jit import JitDriver, hint, unroll_safe, promote
-from pypy.module.micronumpy import signature
 from pypy.module.micronumpy.interp_iter import ConstantIterator
 
 class NumpyEvalFrame(object):
@@ -60,18 +59,25 @@
     greens=['shapelen', 'sig'],
     virtualizables=['frame'],
     reds=['frame', 'arr'],
-    get_printable_location=signature.new_printable_location('numpy'),
+    get_printable_location=get_printable_location,
     name='numpy',
 )
 
+class ComputationDone(Exception):
+    def __init__(self, value):
+        self.value = value
+
 def compute(arr):
     sig = arr.find_sig()
     shapelen = len(arr.shape)
     frame = sig.create_frame(arr)
-    while not frame.done():
-        numpy_driver.jit_merge_point(sig=sig,
-                                     shapelen=shapelen,
-                                     frame=frame, arr=arr)
-        sig.eval(frame, arr)
-        frame.next(shapelen)
-    return frame.cur_value
+    try:
+        while not frame.done():
+            numpy_driver.jit_merge_point(sig=sig,
+                                         shapelen=shapelen,
+                                         frame=frame, arr=arr)
+            sig.eval(frame, arr)
+            frame.next(shapelen)
+        return frame.cur_value
+    except ComputationDone, e:
+        return e.value
diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -3,6 +3,7 @@
 from pypy.module.micronumpy.interp_iter import ConstantIterator, AxisIterator,\
      ViewTransform, BroadcastTransform
 from pypy.tool.pairtype import extendabletype
+from pypy.module.micronumpy.loop import ComputationDone
 
 """ Signature specifies both the numpy expression that has been constructed
 and the assembler to be compiled. This is a very important observation -
@@ -358,10 +359,20 @@
         self.right._create_iter(iterlist, arraylist, arr.right, rtransforms)
 
 class ReduceSignature(Call2):
+    _immutable_fields_ = ['binfunc', 'name', 'calc_dtype',
+                          'left', 'right', 'done_func']
+    
+    def __init__(self, func, name, calc_dtype, left, right,
+                 done_func):
+        Call2.__init__(self, func, name, calc_dtype, left, right)
+        self.done_func = done_func
+        
     def eval(self, frame, arr):
         from pypy.module.micronumpy.interp_numarray import ReduceArray
         assert isinstance(arr, ReduceArray)
         rval = self.right.eval(frame, arr.right).convert_to(self.calc_dtype)
+        if self.done_func is not None and self.done_func(self.calc_dtype, rval):
+            raise ComputationDone(rval)
         frame.cur_value = self.binfunc(self.calc_dtype, frame.cur_value, rval)
 
     def debug_repr(self):
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -347,8 +347,9 @@
         raises((ValueError, TypeError), add.reduce, 1)
 
     def test_reduce_1d(self):
-        from _numpypy import add, maximum
+        from _numpypy import add, maximum, less
 
+        assert less.reduce([5, 4, 3, 2, 1])
         assert add.reduce([1, 2, 3]) == 6
         assert maximum.reduce([1]) == 1
         assert maximum.reduce([1, 2, 3]) == 3


More information about the pypy-commit mailing list