[pypy-commit] extradoc extradoc: more slides and import the sobel demo

antocuni pypy.commits at gmail.com
Mon Jul 10 18:53:55 EDT 2017


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: extradoc
Changeset: r5807:468dc8f9a06b
Date: 2017-07-10 16:20 +0200
http://bitbucket.org/pypy/extradoc/changeset/468dc8f9a06b/

Log:	more slides and import the sobel demo

diff --git a/talk/ep2017/the-joy-of-pypy-jit/Makefile b/talk/ep2017/the-joy-of-pypy-jit/Makefile
--- a/talk/ep2017/the-joy-of-pypy-jit/Makefile
+++ b/talk/ep2017/the-joy-of-pypy-jit/Makefile
@@ -4,11 +4,10 @@
 # WARNING: to work, it needs this patch for docutils
 # https://sourceforge.net/tracker/?func=detail&atid=422032&aid=1459707&group_id=38414
 
-talk.pdf: talk.rst author.latex title.latex stylesheet.latex
+talk.pdf: talk.rst author.latex stylesheet.latex
 	python `which rst2beamer.py` --stylesheet=stylesheet.latex --documentoptions=14pt talk.rst talk.latex || exit
-	#/home/antocuni/.virtualenvs/rst2beamer/bin/python `which rst2beamer.py` --stylesheet=stylesheet.latex --documentoptions=14pt talk.rst talk.latex || exit
+
 	sed 's/\\date{}/\\input{author.latex}/' -i talk.latex || exit
-	#sed 's/\\maketitle/\\input{title.latex}/' -i talk.latex || exit
 	pdflatex talk.latex  || exit
 
 view: talk.pdf
diff --git a/talk/ep2017/the-joy-of-pypy-jit/beamerdefs.txt b/talk/ep2017/the-joy-of-pypy-jit/beamerdefs.txt
--- a/talk/ep2017/the-joy-of-pypy-jit/beamerdefs.txt
+++ b/talk/ep2017/the-joy-of-pypy-jit/beamerdefs.txt
@@ -32,6 +32,11 @@
 
    \sout{
 
+.. |br| raw:: latex
+
+   \vspace{0.3cm}
+
+
 .. closed bracket
 .. ===========================
 
diff --git a/talk/ep2017/the-joy-of-pypy-jit/sobel.png b/talk/ep2017/the-joy-of-pypy-jit/sobel.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b038b17180409163400f447a45bc0e863364d131
GIT binary patch

[cut]

diff --git a/talk/ep2017/the-joy-of-pypy-jit/sobel/benchall.py b/talk/ep2017/the-joy-of-pypy-jit/sobel/benchall.py
new file mode 100644
--- /dev/null
+++ b/talk/ep2017/the-joy-of-pypy-jit/sobel/benchall.py
@@ -0,0 +1,32 @@
+import time
+import pypytools
+from mplayer import mplayer
+import v0, v1, v2, v3
+
+def bench():
+    if pypytools.IS_PYPY:
+        max_frames = 200
+    else:
+        max_frames = 10
+
+    fn = 'test.avi -benchmark'
+    for v in (v0, v1, v2, v3):
+        start = time.time()
+        for i, img in enumerate(mplayer(fn)):
+            out = v.sobel(img)
+            if i == max_frames:
+                break
+        end = time.time()
+        fps = i / (end-start)
+        print '%s: %.2f fps' % (v.__name__, fps)
+
+
+if __name__ == '__main__':
+    try:
+        import pypyjit
+        pypyjit.set_param(trace_limit=200000)
+    except ImportError:
+        pass
+
+    bench()
+
diff --git a/talk/ep2017/the-joy-of-pypy-jit/sobel/main.py b/talk/ep2017/the-joy-of-pypy-jit/sobel/main.py
new file mode 100644
--- /dev/null
+++ b/talk/ep2017/the-joy-of-pypy-jit/sobel/main.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+
+import sys
+import errno
+from time import time
+from mplayer import mplayer, view
+from math import sqrt
+import array
+import v0, v1, v2, v3
+
+def main(argv):
+    if len(argv) > 1:
+        fn = argv[1]
+    else:
+        fn = 'test.avi -benchmark' #+ ' -vf scale=640:480'
+
+    start = start0 = time()
+    for fcnt, img in enumerate(mplayer(fn)):
+        #out = v0.sobel(img)
+        #out = v1.sobel(img)
+        #out = v2.sobel(img)
+        out = v3.sobel(img)
+
+        try:
+            view(out)
+        except IOError, e:
+            if e.errno != errno.EPIPE:
+                raise
+            print 'Exiting'
+            break
+
+        print 1.0 / (time() - start), 'fps, ', (fcnt-2) / (time() - start0), 'average fps'
+        start = time()
+        if fcnt==2:
+            start0 = time()
+
+if __name__ == '__main__':
+    try:
+        import pypyjit
+        pypyjit.set_param(trace_limit=200000)
+    except ImportError:
+        pass
+
+    main(sys.argv)
diff --git a/talk/ep2017/the-joy-of-pypy-jit/sobel/mplayer.py b/talk/ep2017/the-joy-of-pypy-jit/sobel/mplayer.py
new file mode 100644
--- /dev/null
+++ b/talk/ep2017/the-joy-of-pypy-jit/sobel/mplayer.py
@@ -0,0 +1,48 @@
+import os, re, array
+from subprocess import Popen, PIPE, STDOUT
+
+
+def mplayer(fn='tv://', options=''):
+    f = os.popen('mplayer -really-quiet -noframedrop ' + options + ' ' 
+                 '-vo yuv4mpeg:file=/dev/stdout 2>/dev/null </dev/null ' + fn)
+    hdr = f.readline()
+    m = re.search('W(\d+) H(\d+)', hdr)
+    w, h = int(m.group(1)), int(m.group(2))
+    while True:
+        hdr = f.readline()
+        if hdr != 'FRAME\n':
+            break
+        data = array.array('B')
+        data.fromfile(f, w*h) # read luminance data ('Y')
+        f.read(w*h/2) # discard Color data ('U' and 'V')
+        yield w, h, data
+
+class MplayerViewer(object):
+    def __init__(self):
+        self.width = self.height = None
+    def view(self, img):
+        if isinstance(img, tuple):
+            w, h, data = img
+        else:
+            w = img.width
+            h = img.height
+            data = img.data
+        
+        if not self.width:
+            self.mplayer = Popen(['mplayer', '-', '-benchmark',
+                                  '-demuxer', 'rawvideo',
+                                 '-rawvideo', 'w=%d:h=%d:format=y8' % (w, h),
+                                 '-really-quiet'],
+                                 stdin=PIPE, stdout=PIPE, stderr=PIPE)
+            
+            self.width = w
+            self.height = h
+        assert self.width == w
+        assert self.height == h
+        data.tofile(self.mplayer.stdin)
+
+default_viewer = MplayerViewer()
+
+def view(img):
+    default_viewer.view(img)
+    
diff --git a/talk/ep2017/the-joy-of-pypy-jit/sobel/test.avi b/talk/ep2017/the-joy-of-pypy-jit/sobel/test.avi
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e72f9f1b0e99f77baa54aa3f9ef4399b0b82ec45
GIT binary patch

[cut]

diff --git a/talk/ep2017/the-joy-of-pypy-jit/sobel/v0.py b/talk/ep2017/the-joy-of-pypy-jit/sobel/v0.py
new file mode 100644
--- /dev/null
+++ b/talk/ep2017/the-joy-of-pypy-jit/sobel/v0.py
@@ -0,0 +1,29 @@
+import array
+from math import sqrt
+
+def sobel(img):
+    """
+    Low-level version: no abstractions at all
+    """
+    w, h, data = img
+    data_out = array.array('B', [0]) * (w*h)
+    out = w, h, data_out
+    for y in xrange(1, h-1):
+        for x in xrange(1, w-1):
+            dx = (-1.0 * data[(x-1) + w*(y-1)] +
+                   1.0 * data[(x+1) + w*(y-1)] +
+                  -2.0 * data[(x-1) + w*y    ] +
+                   2.0 * data[(x+1) + w*y    ] +
+                  -1.0 * data[(x-1) + w*(y+1)] +
+                   1.0 * data[(x+1) + w*(y+1)])
+            #
+            dy = (-1.0 * data[(x-1) + w*(y-1)] +
+                  -2.0 * data[x     + w*(y-1)] +
+                  -1.0 * data[(x+1) + w*(y-1)] +
+                   1.0 * data[(x-1) + w*(y+1)] +
+                   2.0 * data[x     + w*(y+1)] +
+                   1.0 * data[(x+1) + w*(y+1)])
+            #
+            value = min(int(sqrt(dx*dx + dy*dy) / 2.0), 255)
+            data_out[x + w*y] = value
+    return out
diff --git a/talk/ep2017/the-joy-of-pypy-jit/sobel/v1.py b/talk/ep2017/the-joy-of-pypy-jit/sobel/v1.py
new file mode 100644
--- /dev/null
+++ b/talk/ep2017/the-joy-of-pypy-jit/sobel/v1.py
@@ -0,0 +1,38 @@
+import array
+from math import sqrt
+
+def get(img, x, y):
+    w, h, data = img
+    i = x + y*w
+    return data[i]
+
+def set(img, x, y, value):
+    w, h, data = img
+    i = x + y*w
+    data[i] = value
+
+def sobel(img):
+    """
+    Same as v0, but with get() and set() functions
+    """
+    w, h, data = img
+    out = w, h, array.array('B', [0]) * (w*h)
+    for y in xrange(1, h-1):
+        for x in xrange(1, w-1):
+            dx = (-1.0 * get(img, x-1, y-1) +
+                   1.0 * get(img, x+1, y-1) +
+                  -2.0 * get(img, x-1, y)   +
+                   2.0 * get(img, x+1, y)   +
+                  -1.0 * get(img, x-1, y+1) +
+                   1.0 * get(img, x+1, y+1))
+            #
+            dy = (-1.0 * get(img, x-1, y-1) +
+                  -2.0 * get(img, x,   y-1) +
+                  -1.0 * get(img, x+1, y-1) +
+                   1.0 * get(img, x-1, y+1) +
+                   2.0 * get(img, x,   y+1) +
+                   1.0 * get(img, x+1, y+1))
+            #
+            value = min(int(sqrt(dx*dx + dy*dy) / 2.0), 255)
+            set(out, x, y, value)
+    return out
diff --git a/talk/ep2017/the-joy-of-pypy-jit/sobel/v2.py b/talk/ep2017/the-joy-of-pypy-jit/sobel/v2.py
new file mode 100644
--- /dev/null
+++ b/talk/ep2017/the-joy-of-pypy-jit/sobel/v2.py
@@ -0,0 +1,47 @@
+import array
+from math import sqrt
+
+class Image(object):
+
+    def __init__(self, width, height, data=None):
+        self.width = width
+        self.height = height
+        if data is None:
+            self.data = array.array('B', [0]) * (width*height)
+        else:
+            self.data = data
+
+    def __getitem__(self, idx):
+        x, y = idx
+        return self.data[x + y*self.width]
+
+    def __setitem__(self, idx, value):
+        x, y = idx
+        self.data[x + y*self.width] = value
+
+
+def sobel(img):
+    """
+    Wrap the image inside an Image class
+    """
+    img = Image(*img)
+    out = Image(img.width, img.height)
+    for y in xrange(1, img.height-1):
+        for x in xrange(1, img.width-1):
+            dx = (-1.0 * img[x-1, y-1] +
+                   1.0 * img[x+1, y-1] +
+                  -2.0 * img[x-1, y]   +
+                   2.0 * img[x+1, y]   +
+                  -1.0 * img[x-1, y+1] +
+                   1.0 * img[x+1, y+1])
+            #
+            dy = (-1.0 * img[x-1, y-1] +
+                  -2.0 * img[x,   y-1] +
+                  -1.0 * img[x+1, y-1] +
+                   1.0 * img[x-1, y+1] +
+                   2.0 * img[x,   y+1] +
+                   1.0 * img[x+1, y+1])
+            #
+            value = min(int(sqrt(dx*dx + dy*dy) / 2.0), 255)
+            out[x, y] = value
+    return out
diff --git a/talk/ep2017/the-joy-of-pypy-jit/sobel/v3.py b/talk/ep2017/the-joy-of-pypy-jit/sobel/v3.py
new file mode 100644
--- /dev/null
+++ b/talk/ep2017/the-joy-of-pypy-jit/sobel/v3.py
@@ -0,0 +1,57 @@
+import itertools
+import array
+from collections import namedtuple
+from math import sqrt
+import v2
+
+_Point = namedtuple('_Point', ['x', 'y'])
+class Point(_Point):
+
+    def __add__(self, other):
+        ox, oy = other
+        x = self.x + ox
+        y = self.y + oy
+        return self.__class__(x, y)
+
+
+class ImageIter(object):
+
+    def __init__(self, x0, x1, y0, y1):
+        self.it = itertools.product(xrange(x0, x1), xrange(y0, y1))
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        x, y = next(self.it)
+        return Point(x, y)
+
+
+class Image(v2.Image):
+
+    def noborder(self):
+        return ImageIter(1, self.width-1, 1, self.height-1)
+
+
+def sobel(img):
+    img = Image(*img)
+    out = Image(img.width, img.height)
+    for p in img.noborder():
+        dx = (-1.0 * img[p + (-1,-1)] +
+               1.0 * img[p + ( 1,-1)] + 
+              -2.0 * img[p + (-1, 0)] +
+               2.0 * img[p + ( 1, 0)] + 
+              -1.0 * img[p + (-1, 1)] +
+               1.0 * img[p + ( 1, 1)])
+        #
+        dy = (-1.0 * img[p + (-1,-1)] +
+              -2.0 * img[p + ( 0,-1)] +
+              -1.0 * img[p + ( 1,-1)] + 
+               1.0 * img[p + (-1, 1)] +
+               2.0 * img[p + ( 0, 1)] +
+               1.0 * img[p + ( 1, 1)])
+        #
+        value = min(int(sqrt(dx*dx + dy*dy) / 2.0), 255)
+        out[p] = value
+    return out
+
diff --git a/talk/ep2017/the-joy-of-pypy-jit/speed.png b/talk/ep2017/the-joy-of-pypy-jit/speed.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c09730c0d7d264cec8ad2c93ace4eeed5149b335
GIT binary patch

[cut]

diff --git a/talk/ep2017/the-joy-of-pypy-jit/talk.rst b/talk/ep2017/the-joy-of-pypy-jit/talk.rst
--- a/talk/ep2017/the-joy-of-pypy-jit/talk.rst
+++ b/talk/ep2017/the-joy-of-pypy-jit/talk.rst
@@ -11,8 +11,118 @@
 
 - ``pdb++``, ``cffi``, ``vmprof``, ``capnpy``, ...
 
-- Consultant, trainer
+- @antocuni
 
 - http://antocuni.eu
 
 
+General question
+----------------
+
+Q: "How fast is PyPy?"
+
+|pause|
+
+A: "It depends"
+
+
+speed.pypy.org
+---------------
+
+.. image:: speed.png
+   :scale: 40%
+           
+
+The joy of PyPy
+----------------
+
+- No single "speedup" factor
+
+- The better the code, the greater the speedup
+
+           
+Good code
+---------
+
+- Correct
+
+- Readable
+
+- Easy to maintain
+
+- Nice APIs
+
+- Fast
+
+
+Abstractions
+------------
+
+- functions
+
+- classes
+
+- inheritance
+
+- etc.
+
+- PRO: readability
+  
+- CON: speed?
+
+  
+Example: Sobel filter
+----------------------
+
+Edge detection
+|br|
+   
+.. image:: sobel.png
+       :scale: 40%
+
+
+Image
+-----
+
+- greyscale
+
+- `w`, `h`
+
+- `array.array('B')` of `w * h` bytes
+
+- pixel `(x, y)` at index `x + w*y`
+
+
+Version 0
+---------
+
+|scriptsize|
+
+.. sourcecode:: python
+
+    def sobel(img):
+        w, h, data = img
+        data_out = array.array('B', [0]) * (w*h)
+        out = w, h, data_out
+        for y in xrange(1, h-1):
+            for x in xrange(1, w-1):
+                dx = (-1.0 * data[(x-1) + w*(y-1)] +
+                       1.0 * data[(x+1) + w*(y-1)] +
+                      -2.0 * data[(x-1) + w*y    ] +
+                       2.0 * data[(x+1) + w*y    ] +
+                      -1.0 * data[(x-1) + w*(y+1)] +
+                       1.0 * data[(x+1) + w*(y+1)])
+ 
+                dy = (-1.0 * data[(x-1) + w*(y-1)] +
+                      -2.0 * data[x     + w*(y-1)] +
+                      -1.0 * data[(x+1) + w*(y-1)] +
+                       1.0 * data[(x-1) + w*(y+1)] +
+                       2.0 * data[x     + w*(y+1)] +
+                       1.0 * data[(x+1) + w*(y+1)])
+ 
+                value = min(int(sqrt(dx*dx + dy*dy) / 2.0), 255)
+                data_out[x + w*y] = value
+        return out
+ 
+|end_scriptsize|
+


More information about the pypy-commit mailing list