[pypy-commit] pypy numpy-single-jitdriver: shuffle stuff around so reduce does not need it's own jitdriver. 16 LOC removed

fijal noreply at buildbot.pypy.org
Thu Feb 2 17:40:45 CET 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: numpy-single-jitdriver
Changeset: r52035:ef9343793d60
Date: 2012-02-02 18:40 +0200
http://bitbucket.org/pypy/pypy/changeset/ef9343793d60/

Log:	shuffle stuff around so reduce does not need it's own jitdriver. 16
	LOC removed WIN!

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
@@ -17,13 +17,6 @@
 from pypy.module.micronumpy.appbridge import get_appbridge_cache
 
 
-numpy_driver = jit.JitDriver(
-    greens=['shapelen', 'sig'],
-    virtualizables=['frame'],
-    reds=['result_size', 'frame', 'ri', 'self', 'result'],
-    get_printable_location=signature.new_printable_location('numpy'),
-    name='numpy',
-)
 all_driver = jit.JitDriver(
     greens=['shapelen', 'sig'],
     virtualizables=['frame'],
@@ -685,6 +678,9 @@
         raise OperationError(space.w_NotImplementedError, space.wrap(
             "non-int arg not supported"))
 
+    def compute_first_step(self, sig, frame):
+        pass
+
 def convert_to_array(space, w_obj):
     if isinstance(w_obj, BaseArray):
         return w_obj
@@ -811,7 +807,8 @@
     def create_sig(self):
         if self.forced_result is not None:
             return self.forced_result.create_sig()
-        return signature.Call1(self.ufunc, self.name, self.values.create_sig())
+        return signature.Call1(self.ufunc, self.name, self.calc_dtype,
+                               self.values.create_sig())
 
 class Call2(VirtualArray):
     """
@@ -852,10 +849,6 @@
         return signature.Call2(self.ufunc, self.name, self.calc_dtype,
                                self.left.create_sig(), self.right.create_sig())
 
-class ComputationArray(BaseArray):
-    """ A base class for all objects that describe operations for computation
-    """
-
 class ResultArray(Call2):
     def __init__(self, child, size, shape, dtype, res=None, order='C'): 
         if res is None:
@@ -866,12 +859,25 @@
         return signature.ResultSignature(self.res_dtype, self.left.create_sig(),
                                          self.right.create_sig())
 
-class Reduce(ComputationArray):
-    def __init__(self):
-        pass
+class ReduceArray(Call2):
+    def __init__(self, func, name, identity, child, dtype):
+        self.identity = identity
+        Call2.__init__(self, func, name, [1], dtype, dtype, None, child)
+
+    def compute_first_step(self, sig, frame):
+        assert isinstance(sig, signature.ReduceSignature)
+        if self.identity is None:
+            frame.cur_value = sig.right.eval(frame, self).convert_to(
+                self.calc_dtype)
+            frame.next(len(self.right.shape))
+        else:
+            frame.cur_value = self.identity.convert_to(self.calc_dtype)
+
     
     def create_sig(self):
-        return signature.ReduceSignature(self.func)
+        return signature.ReduceSignature(self.ufunc, self.name, self.res_dtype,
+                                 signature.ScalarSignature(self.res_dtype),
+                                         self.right.create_sig())
 
 class SliceArray(Call2):
     def __init__(self, shape, dtype, left, right, no_broadcast=False):
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
@@ -3,21 +3,13 @@
 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.signature import (ReduceSignature, find_sig,
+from pypy.module.micronumpy.signature import (find_sig,
     new_printable_location, AxisReduceSignature, ScalarSignature)
 from pypy.rlib import jit
 from pypy.rlib.rarithmetic import LONG_BIT
 from pypy.tool.sourcetools import func_with_new_name
 
 
-reduce_driver = jit.JitDriver(
-    greens=['shapelen', "sig"],
-    virtualizables=["frame"],
-    reds=["frame", "self", "dtype", "value", "obj"],
-    get_printable_location=new_printable_location('reduce'),
-    name='numpy_reduce',
-)
-
 axisreduce_driver = jit.JitDriver(
     greens=['shapelen', 'sig'],
     virtualizables=['frame'],
@@ -140,7 +132,9 @@
     def reduce(self, space, w_obj, multidim, promote_to_largest, dim,
                keepdims=False):
         from pypy.module.micronumpy.interp_numarray import convert_to_array, \
-                                                           Scalar
+                                                           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"))
@@ -166,17 +160,8 @@
         if shapelen > 1 and dim >= 0:
             res = self.do_axis_reduce(obj, dtype, dim, keepdims)
             return space.wrap(res)
-        scalarsig = ScalarSignature(dtype)
-        sig = find_sig(ReduceSignature(self.func, self.name, dtype,
-                                       scalarsig,
-                                       obj.create_sig()), obj)
-        frame = sig.create_frame(obj)
-        if self.identity is None:
-            value = sig.eval(frame, obj).convert_to(dtype)
-            frame.next(shapelen)
-        else:
-            value = self.identity.convert_to(dtype)
-        return self.reduce_loop(shapelen, sig, frame, value, obj, dtype)
+        arr = ReduceArray(self.func, self.name, self.identity, obj, dtype)
+        return loop.compute(arr)
 
     def do_axis_reduce(self, obj, dtype, dim, keepdims):
         from pypy.module.micronumpy.interp_numarray import AxisReduce,\
@@ -229,19 +214,6 @@
             arr.left.setitem(iterator.offset, value)
             frame.next(shapelen)
 
-    def reduce_loop(self, shapelen, sig, frame, value, obj, dtype):
-        while not frame.done():
-            reduce_driver.jit_merge_point(sig=sig,
-                                          shapelen=shapelen, self=self,
-                                          value=value, obj=obj, frame=frame,
-                                          dtype=dtype)
-            assert isinstance(sig, ReduceSignature)
-            value = sig.binfunc(dtype, value,
-                                sig.eval(frame, obj).convert_to(dtype))
-            frame.next(shapelen)
-        return value
-
-
 class W_Ufunc1(W_Ufunc):
     argcount = 1
 
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
@@ -3,8 +3,55 @@
 signatures
 """
 
-from pypy.rlib.jit import JitDriver
+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):
+    _virtualizable2_ = ['iterators[*]', 'final_iter', 'arraylist[*]',
+                        'value', 'identity', 'cur_value']
+
+    @unroll_safe
+    def __init__(self, iterators, arrays, identity=None):
+        self = hint(self, access_directly=True, fresh_virtualizable=True)
+        self.iterators = iterators[:]
+        self.arrays = arrays[:]
+        for i in range(len(self.iterators)):
+            iter = self.iterators[i]
+            if not isinstance(iter, ConstantIterator):
+                self.final_iter = i
+                break
+        else:
+            self.final_iter = -1
+        self.cur_value = None
+        self.identity = identity
+
+    def done(self):
+        final_iter = promote(self.final_iter)
+        if final_iter < 0:
+            assert False
+        return self.iterators[final_iter].done()
+
+    @unroll_safe
+    def next(self, shapelen):
+        for i in range(len(self.iterators)):
+            self.iterators[i] = self.iterators[i].next(shapelen)
+
+    @unroll_safe
+    def next_from_second(self, shapelen):
+        """ Don't increase the first iterator
+        """
+        for i in range(1, len(self.iterators)):
+            self.iterators[i] = self.iterators[i].next(shapelen)
+
+    def next_first(self, shapelen):
+        self.iterators[0] = self.iterators[0].next(shapelen)
+
+    def get_final_iter(self):
+        final_iter = promote(self.final_iter)
+        if final_iter < 0:
+            assert False
+        return self.iterators[final_iter]
 
 def get_printable_location(shapelen, sig):
     return 'numpy ' + sig.debug_repr() + ' [%d dims]' % (shapelen,)
@@ -27,4 +74,4 @@
                                      frame=frame, arr=arr)
         sig.eval(frame, arr)
         frame.next(shapelen)
-
+    return frame.cur_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
@@ -1,9 +1,7 @@
 from pypy.rlib.objectmodel import r_dict, compute_identity_hash, compute_hash
 from pypy.rlib.rarithmetic import intmask
-from pypy.module.micronumpy.interp_iter import ViewIterator, ArrayIterator, \
-     ConstantIterator, AxisIterator, ViewTransform,\
-     BroadcastTransform
-from pypy.rlib.jit import hint, unroll_safe, promote
+from pypy.module.micronumpy.interp_iter import ConstantIterator, AxisIterator,\
+     ViewTransform, BroadcastTransform
 from pypy.tool.pairtype import extendabletype
 
 """ Signature specifies both the numpy expression that has been constructed
@@ -55,50 +53,6 @@
         known_sigs[sig] = sig
         return sig
 
-class NumpyEvalFrame(object):
-    _virtualizable2_ = ['iterators[*]', 'final_iter', 'arraylist[*]',
-                        'value', 'identity']
-
-    @unroll_safe
-    def __init__(self, iterators, arrays):
-        self = hint(self, access_directly=True, fresh_virtualizable=True)
-        self.iterators = iterators[:]
-        self.arrays = arrays[:]
-        for i in range(len(self.iterators)):
-            iter = self.iterators[i]
-            if not isinstance(iter, ConstantIterator):
-                self.final_iter = i
-                break
-        else:
-            self.final_iter = -1
-
-    def done(self):
-        final_iter = promote(self.final_iter)
-        if final_iter < 0:
-            assert False
-        return self.iterators[final_iter].done()
-
-    @unroll_safe
-    def next(self, shapelen):
-        for i in range(len(self.iterators)):
-            self.iterators[i] = self.iterators[i].next(shapelen)
-
-    @unroll_safe
-    def next_from_second(self, shapelen):
-        """ Don't increase the first iterator
-        """
-        for i in range(1, len(self.iterators)):
-            self.iterators[i] = self.iterators[i].next(shapelen)
-
-    def next_first(self, shapelen):
-        self.iterators[0] = self.iterators[0].next(shapelen)
-
-    def get_final_iter(self):
-        final_iter = promote(self.final_iter)
-        if final_iter < 0:
-            assert False
-        return self.iterators[final_iter]
-
 def _add_ptr_to_cache(ptr, cache):
     i = 0
     for p in cache:
@@ -141,10 +95,20 @@
         self.iter_no = no
 
     def create_frame(self, arr):
+        from pypy.module.micronumpy.loop import NumpyEvalFrame
+        from pypy.module.micronumpy.interp_numarray import ReduceArray
+        
         iterlist = []
         arraylist = []
         self._create_iter(iterlist, arraylist, arr, [])
-        return NumpyEvalFrame(iterlist, arraylist)
+        if isinstance(arr, ReduceArray):
+            identity = arr.identity
+        else:
+            identity = None
+        f = NumpyEvalFrame(iterlist, arraylist, identity)
+        # hook for cur_value being used by reduce
+        arr.compute_first_step(self, f)
+        return f
 
 class ConcreteSignature(Signature):
     _immutable_fields_ = ['dtype']
@@ -256,12 +220,13 @@
         return self.child.eval(frame, arr.child)
 
 class Call1(Signature):
-    _immutable_fields_ = ['unfunc', 'name', 'child']
+    _immutable_fields_ = ['unfunc', 'name', 'child', 'dtype']
 
-    def __init__(self, func, name, child):
+    def __init__(self, func, name, dtype, child):
         self.unfunc = func
         self.child = child
         self.name = name
+        self.dtype = dtype
 
     def hash(self):
         return compute_hash(self.name) ^ intmask(self.child.hash() << 1)
@@ -398,20 +363,14 @@
         self.right._create_iter(iterlist, arraylist, arr.right, rtransforms)
 
 class ReduceSignature(Call2):
-    def _create_iter(self, iterlist, arraylist, arr, transforms):
-        self.right._create_iter(iterlist, arraylist, arr, transforms)
-
-    def _invent_numbering(self, cache, allnumbers):
-        self.right._invent_numbering(cache, allnumbers)
-
-    def _invent_array_numbering(self, arr, cache):
-        self.right._invent_array_numbering(arr, cache)
-
     def eval(self, frame, arr):
-        return self.right.eval(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)
+        frame.cur_value = self.binfunc(self.calc_dtype, frame.cur_value, rval)
 
     def debug_repr(self):
-        return 'ReduceSig(%s, %s)' % (self.name, self.right.debug_repr())
+        return 'ReduceSig(%s)' % (self.name, self.right.debug_repr())
 
 class SliceloopSignature(Call2):
     def eval(self, frame, arr):


More information about the pypy-commit mailing list