[pypy-commit] pypy default: optimize and test ndarray flatiter get/set
bdkearns
noreply at buildbot.pypy.org
Thu Oct 9 05:59:47 CEST 2014
Author: Brian Kearns <bdkearns at gmail.com>
Branch:
Changeset: r73849:7842e64c5847
Date: 2014-10-08 13:23 -0400
http://bitbucket.org/pypy/pypy/changeset/7842e64c5847/
Log: optimize and test ndarray flatiter get/set
diff --git a/pypy/module/micronumpy/flatiter.py b/pypy/module/micronumpy/flatiter.py
--- a/pypy/module/micronumpy/flatiter.py
+++ b/pypy/module/micronumpy/flatiter.py
@@ -27,12 +27,9 @@
class W_FlatIterator(W_NDimArray):
def __init__(self, arr):
self.base = arr
+ self.iter, self.state = arr.create_iter()
# this is needed to support W_NDimArray interface
self.implementation = FakeArrayImplementation(self.base)
- self.reset()
-
- def reset(self):
- self.iter, self.state = self.base.create_iter()
def descr_len(self, space):
return space.wrap(self.iter.size)
@@ -54,25 +51,39 @@
if not (space.isinstance_w(w_idx, space.w_int) or
space.isinstance_w(w_idx, space.w_slice)):
raise oefmt(space.w_IndexError, 'unsupported iterator index')
- self.reset()
- base = self.base
- start, stop, step, length = space.decode_index4(w_idx, base.get_size())
- base_iter, base_state = base.create_iter()
- base_state = base_iter.next_skip_x(base_state, start)
- if length == 1:
- return base_iter.getitem(base_state)
- res = W_NDimArray.from_shape(space, [length], base.get_dtype(),
- base.get_order(), w_instance=base)
- return loop.flatiter_getitem(res, base_iter, base_state, step)
+ self.state = self.iter.reset(self.state)
+ start, stop, step, length = space.decode_index4(w_idx, self.iter.size)
+ self.state = self.iter.next_skip_x(self.state, start)
+ try:
+ if length == 1:
+ return self.iter.getitem(self.state)
+ base = self.base
+ res = W_NDimArray.from_shape(space, [length], base.get_dtype(),
+ base.get_order(), w_instance=base)
+ return loop.flatiter_getitem(res, self.iter, self.state, step)
+ finally:
+ self.state = self.iter.reset(self.state)
def descr_setitem(self, space, w_idx, w_value):
if not (space.isinstance_w(w_idx, space.w_int) or
space.isinstance_w(w_idx, space.w_slice)):
raise oefmt(space.w_IndexError, 'unsupported iterator index')
- base = self.base
- start, stop, step, length = space.decode_index4(w_idx, base.get_size())
- arr = convert_to_array(space, w_value)
- loop.flatiter_setitem(space, self.base, arr, start, step, length)
+ start, stop, step, length = space.decode_index4(w_idx, self.iter.size)
+ self.state = self.iter.reset(self.state)
+ self.state = self.iter.next_skip_x(self.state, start)
+ try:
+ dtype = self.base.get_dtype()
+ if length == 1:
+ try:
+ val = dtype.coerce(space, w_value)
+ except OperationError:
+ raise oefmt(space.w_ValueError, "Error setting single item of array.")
+ self.iter.setitem(self.state, val)
+ return
+ arr = convert_to_array(space, w_value)
+ loop.flatiter_setitem(space, dtype, arr, self.iter, self.state, step, length)
+ finally:
+ self.state = self.iter.reset(self.state)
def descr_iter(self):
return self
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
@@ -443,11 +443,8 @@
greens = ['dtype'],
reds = 'auto')
-def flatiter_setitem(space, arr, val, start, step, length):
- dtype = arr.get_dtype()
- arr_iter, arr_state = arr.create_iter()
+def flatiter_setitem(space, dtype, val, arr_iter, arr_state, step, length):
val_iter, val_state = val.create_iter()
- arr_state = arr_iter.next_skip_x(arr_state, start)
while length > 0:
flatiter_setitem_driver.jit_merge_point(dtype=dtype)
val = val_iter.getitem(val_state)
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -475,8 +475,10 @@
return repeat(space, self, repeats, w_axis)
def descr_set_flatiter(self, space, w_obj):
+ iter, state = self.create_iter()
+ dtype = self.get_dtype()
arr = convert_to_array(space, w_obj)
- loop.flatiter_setitem(space, self, arr, 0, 1, self.get_size())
+ loop.flatiter_setitem(space, dtype, arr, iter, state, 1, iter.size)
def descr_get_flatiter(self, space):
return space.wrap(W_FlatIterator(self))
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -2727,15 +2727,35 @@
b.next()
assert b.index == 3
assert b.coords == (0, 3)
+ b.next()
assert b[3] == 3
- assert (b[::3] == [0, 3, 6, 9]).all()
- assert (b[2::5] == [2, 7]).all()
- assert b[-2] == 8
- raises(IndexError, "b[11]")
- raises(IndexError, "b[-11]")
- raises(IndexError, 'b[0, 1]')
assert b.index == 0
assert b.coords == (0, 0)
+ b.next()
+ assert (b[::3] == [0, 3, 6, 9]).all()
+ assert b.index == 0
+ assert b.coords == (0, 0)
+ b.next()
+ assert (b[2::5] == [2, 7]).all()
+ assert b.index == 0
+ assert b.coords == (0, 0)
+ b.next()
+ assert b[-2] == 8
+ assert b.index == 0
+ assert b.coords == (0, 0)
+ b.next()
+ raises(IndexError, "b[11]")
+ assert b.index == 0
+ assert b.coords == (0, 0)
+ b.next()
+ raises(IndexError, "b[-11]")
+ assert b.index == 0
+ assert b.coords == (0, 0)
+ b.next()
+ exc = raises(IndexError, 'b[0, 1]')
+ assert str(exc.value) == "unsupported iterator index"
+ assert b.index == 1
+ assert b.coords == (0, 1)
def test_flatiter_setitem(self):
from numpypy import arange, array
@@ -2743,9 +2763,25 @@
b = a.T.flat
b[6::2] = [-1, -2]
assert (a == [[0, 1, -1, 3], [4, 5, 6, -1], [8, 9, -2, 11]]).all()
+ assert b[2] == 8
+ assert b.index == 0
+ b.next()
+ b[6::2] = [-21, -42]
+ assert (a == [[0, 1, -21, 3], [4, 5, 6, -21], [8, 9, -42, 11]]).all()
b[0:2] = [[[100]]]
assert(a[0,0] == 100)
assert(a[1,0] == 100)
+ b.next()
+ assert b.index == 1
+ exc = raises(ValueError, "b[0] = [1, 2]")
+ assert str(exc.value) == "Error setting single item of array."
+ assert b.index == 0
+ b.next()
+ raises(IndexError, "b[100] = 42")
+ assert b.index == 1
+ exc = raises(IndexError, "b[0, 1] = 42")
+ assert str(exc.value) == "unsupported iterator index"
+ assert b.index == 1
def test_flatiter_ops(self):
from numpypy import arange, array
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -77,3 +77,119 @@
--TICK--
jump(p0, p1, p3, p6, p7, p12, p14, f86, p18, i87, i62, p41, i58, p47, i40, i64, i70, descr=...)
""")
+
+ def test_array_flatiter_getitem_single(self):
+ def main():
+ import _numpypy.multiarray as np
+ arr = np.zeros((1024, 16)) + 42
+ ai = arr.flat
+ i = 0
+ while i < arr.size:
+ a = ai[i]
+ i += 1
+ return a
+ log = self.run(main, [])
+ assert log.result == 42.0
+ loop, = log.loops_by_filename(self.filepath)
+ assert loop.match("""
+ i123 = int_lt(i112, i44)
+ guard_true(i123, descr=...)
+ p124 = getfield_gc_pure(p121, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices 16>)
+ setarrayitem_gc(p124, 1, 0, descr=<ArrayS 8>)
+ setarrayitem_gc(p124, 0, 0, descr=<ArrayS 8>)
+ i126 = int_lt(i112, i65)
+ guard_true(i126, descr=...)
+ i127 = int_sub(i75, i112)
+ i128 = int_lt(0, i127)
+ guard_false(i128, descr=...)
+ i129 = int_floordiv(i112, i75)
+ i130 = int_mul(i129, i75)
+ i131 = int_sub(i112, i130)
+ i132 = int_rshift(i131, 63)
+ i133 = int_add(i129, i132)
+ i134 = int_mul(i133, i75)
+ i135 = int_sub(i112, i134)
+ i136 = int_mul(i91, i135)
+ i137 = int_add(i64, i136)
+ i138 = int_sub(i98, i133)
+ setarrayitem_gc(p124, 1, i135, descr=<ArrayS 8>)
+ i139 = int_lt(0, i138)
+ guard_true(i139, descr=...)
+ i140 = int_mul(i102, i133)
+ i141 = int_add(i137, i140)
+ f142 = raw_load(i108, i141, descr=<ArrayF 8>)
+ i143 = int_add(i112, 1)
+ setarrayitem_gc(p124, 1, 0, descr=<ArrayS 8>)
+ guard_not_invalidated(descr=...)
+ i144 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value 0>)
+ i145 = int_lt(i144, 0)
+ guard_false(i145, descr=...)
+ p146 = new_with_vtable(...)
+ setfield_gc(p146, p49, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_iterator 24>)
+ setfield_gc(p146, p124, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices 16>)
+ setfield_gc(p146, i64, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_offset 32>)
+ setfield_gc(p146, 0, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_index 8>)
+ setfield_gc(p16, p146, descr=<FieldP pypy.module.micronumpy.flatiter.W_FlatIterator.inst_state 56>)
+ i147 = arraylen_gc(p72, descr=<ArrayS 8>)
+ i148 = arraylen_gc(p90, descr=<ArrayS 8>)
+ jump(p0, p1, p3, p6, p7, p12, p14, p16, i143, f142, p26, i44, p146, i65, p49, i64, i75, i91, i98, i102, i108, p72, p90, descr=...)
+ """)
+
+ def test_array_flatiter_setitem_single(self):
+ def main():
+ import _numpypy.multiarray as np
+ arr = np.empty((1024, 16))
+ ai = arr.flat
+ i = 0
+ while i < arr.size:
+ ai[i] = 42.0
+ i += 1
+ return ai[-1]
+ log = self.run(main, [])
+ assert log.result == 42.0
+ loop, = log.loops_by_filename(self.filepath)
+ assert loop.match("""
+ i126 = int_lt(i115, i42)
+ guard_true(i126, descr=...)
+ i127 = int_lt(i115, i48)
+ guard_true(i127, descr=...)
+ p128 = getfield_gc_pure(p124, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices 16>)
+ i129 = int_sub(i73, i115)
+ setarrayitem_gc(p128, 1, 0, descr=<ArrayS 8>)
+ setarrayitem_gc(p128, 0, 0, descr=<ArrayS 8>)
+ i131 = int_lt(0, i129)
+ guard_false(i131, descr=...)
+ i132 = int_floordiv(i115, i73)
+ i133 = int_mul(i132, i73)
+ i134 = int_sub(i115, i133)
+ i135 = int_rshift(i134, 63)
+ i136 = int_add(i132, i135)
+ i137 = int_mul(i136, i73)
+ i138 = int_sub(i115, i137)
+ i139 = int_mul(i89, i138)
+ i140 = int_add(i66, i139)
+ i141 = int_sub(i96, i136)
+ setarrayitem_gc(p128, 1, i138, descr=<ArrayS 8>)
+ i142 = int_lt(0, i141)
+ guard_true(i142, descr=...)
+ i143 = int_mul(i100, i136)
+ i144 = int_add(i140, i143)
+ setarrayitem_gc(p128, 0, i136, descr=<ArrayS 8>)
+ guard_not_invalidated(descr=...)
+ raw_store(i111, i144, 42.000000, descr=<ArrayF 8>)
+ i146 = int_add(i115, 1)
+ i147 = getfield_raw(ticker_address, descr=<FieldS pypysig_long_struct.c_value 0>)
+ setarrayitem_gc(p128, 1, 0, descr=<ArrayS 8>)
+ setarrayitem_gc(p128, 0, 0, descr=<ArrayS 8>)
+ i149 = int_lt(i147, 0)
+ guard_false(i149, descr=...)
+ p150 = new_with_vtable(...)
+ setfield_gc(p150, p47, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_iterator 24>)
+ setfield_gc(p150, p128, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_indices 16>)
+ setfield_gc(p150, i66, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_offset 32>)
+ setfield_gc(p150, 0, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_index 8>)
+ setfield_gc(p16, p150, descr=<FieldP pypy.module.micronumpy.flatiter.W_FlatIterator.inst_state 56>)
+ i151 = arraylen_gc(p70, descr=<ArrayS 8>)
+ i152 = arraylen_gc(p88, descr=<ArrayS 8>)
+ jump(p0, p1, p3, p6, p7, p12, p14, p16, i146, i42, i48, p150, i73, i66, p47, i89, i96, i100, i111, p70, p88, descr=...)
+ """)
More information about the pypy-commit
mailing list