summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorMark Wiebe <mwwiebe@gmail.com>2010-12-21 14:51:42 -0800
committerMark Wiebe <mwwiebe@gmail.com>2010-12-21 14:51:42 -0800
commit44ba4e3501d6c8438ee2132dc917fc22663bf38b (patch)
tree9280d6fe1d09e612f1abf86aafed6c5744b1744b /doc
parent01ce669508080fd2d4c1f9c246a1a4260a2f2cb9 (diff)
downloadnumpy-44ba4e3501d6c8438ee2132dc917fc22663bf38b.tar.gz
NEP: iter: Added Lambda UFunc example
Diffstat (limited to 'doc')
-rw-r--r--doc/neps/new-iterator-ufunc.rst57
1 files changed, 55 insertions, 2 deletions
diff --git a/doc/neps/new-iterator-ufunc.rst b/doc/neps/new-iterator-ufunc.rst
index 4c1559ace..f5e4f7883 100644
--- a/doc/neps/new-iterator-ufunc.rst
+++ b/doc/neps/new-iterator-ufunc.rst
@@ -1243,8 +1243,61 @@ references, and add ``NPY_ITER_WRITEABLE_REFERENCES`` to the flags.::
return ret;
}
-Python Example
---------------
+Python Lambda UFunc Example
+---------------------------
+
+To show how the new iterator allows the definition of efficient UFunc-like
+functions in pure Python, we demonstrate the function ``luf``, which
+makes a lambda-expression act like a UFunc. This is very similar to the
+``numexpr`` library, but only takes a few lines of code.
+
+First, here is the definition of the ``luf`` function.::
+
+ def luf(lamdaexpr, *args, **kwargs):
+ """Lambda UFunc
+
+ e.g.
+ c = luf(lambda i,j:i+j, a, b, order='K',
+ casting='safe', buffersize=8192)
+
+ c = np.empty(...)
+ luf(lambda i,j:i+j, a, b, order='K',
+ casting='safe', buffersize=8192)
+ """
+
+ nargs = len(args)
+ op = args + (kwargs.get('out',None),)
+ it = np.newiter(op, ['buffered','no_inner_iteration'],
+ [['readonly','nbo_aligned']]*nargs +
+ [['writeonly','allocate','no_broadcast']],
+ order=kwargs.get('order','K'),
+ casting=kwargs.get('casting','safe'),
+ buffersize=kwargs.get('buffersize',0))
+ while not it.finished:
+ it[-1] = lamdaexpr(*it[:-1])
+ it.iternext()
+
+ return it.operands[-1]
+
+Then, by using ``luf`` instead of straight Python expressions, we
+can gain some performance from better cache behavior.::
+
+ In [2]: a = np.random.random((50,50,50,10))
+ In [3]: b = np.random.random((50,50,1,10))
+ In [4]: c = np.random.random((50,50,50,1))
+
+ In [5]: timeit 3*a+b-(a/c)
+ 1 loops, best of 3: 138 ms per loop
+
+ In [6]: timeit luf(lambda a,b,c:3*a+b-(a/c), a, b, c)
+ 10 loops, best of 3: 60.9 ms per loop
+
+ In [7]: np.all(3*a+b-(a/c) == luf(lambda a,b,c:3*a+b-(a/c), a, b, c))
+ Out[7]: True
+
+
+Python Addition Example
+-----------------------
The iterator has been mostly written and exposed to Python. To
see how it behaves, let's see what we can do with the np.add ufunc.