Skip to content

Commit

Permalink
fix bugs, add fractal_ctypes.py
Browse files Browse the repository at this point in the history
  • Loading branch information
mattip committed Jun 13, 2017
1 parent c2df8df commit c89e55e
Show file tree
Hide file tree
Showing 3 changed files with 234 additions and 164 deletions.
40 changes: 19 additions & 21 deletions create_fractal.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
#And for desert:
import sys
print(sys.executable)
from timeit import default_timer as timer
import cffi
from PIL import Image

ffi = cffi.FFI()
from __future__ import print_function, division

class Img(object):
def __init__(self, width, height):
self.width = width
self.height = height
self.data = ffi.new('uint8_t[%d]' % (width*height,))
self.data = bytearray(width*height)

def create_fractal(image, iters, func, oneval):
''' Call a function for each pixel in the image, where
Expand Down Expand Up @@ -45,15 +38,20 @@ def mandel(x, y, max_iters, value):
value[0] = max_iters
return max_iters

# Pure python
width = 1500
height = 1000
image = Img(width, height)
s = timer()
oneval = ffi.new('uint8_t[1]')
create_fractal(image, 20, mandel, oneval)
e = timer()
pure_pypy = e - s
print('pure pypy required {:.2f} millisecs'.format(pure_pypy))
im = Image.fromarray(image.data.reshape(height, width))
im.save('pypyy.png')
if __name__ == '__main__':
from timeit import default_timer as timer
from PIL import Image
# Pure python
width = 1500
height = 1000
image = Img(width, height)
s = timer()
oneval = bytearray(1)
create_fractal(image, 20, mandel, oneval)
e = timer()
elapsed = e - s
import platform
imp = platform.python_implementation().lower()
print('pure {} required {:.2f} millisecs'.format(imp, 1000*elapsed))
im = Image.frombuffer("L", (width, height), image.data, "raw", "L", 0, 1)
im.save('{}.png'.format(imp))
74 changes: 74 additions & 0 deletions fractal_ctypes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from __future__ import print_function, division
import subprocess
import os

width = 1500
height = 1000
#ctypes
# First all the declarations. Each function and struct must be redefined ...
import ctypes

class CtypesImg(ctypes.Structure):
_fields_ = [('width', ctypes.c_int),
('height', ctypes.c_int),
('data', ctypes.POINTER(ctypes.c_uint8)), # HUH?
]
array_cache = {}
def __init__(self, width, height):
self.width = width
self.height = height
# Create a class type to hold the data.
# Since this creates a type, cache it for reuse rather
# than create a new one each time
if width*height not in self.array_cache:
self.array_cache[width*height] = ctypes.c_uint8 * (width * height)
# Note this keeps the img.data alive in the interpreter
self.data = self.array_cache[width*height]() # !!!!!!

def asmemoryview(self):
# There must be a better way, but this code will not
# be timed, so explicit trumps implicit
ret = self.array_cache[width*height]()
for i in range(width*height):
ret[i] = self.data[i]
return ret

ctypesimg = CtypesImg(width, height)


# Load the DLL
cdll = ctypes.cdll.LoadLibrary('./libcreate_fractal.so')

#Fish the function pointers from the DLL and define the interfaces
create_fractal_ctypes = cdll.create_fractal
create_fractal_ctypes.argtypes = [CtypesImg, ctypes.c_int]

mandel_ctypes = cdll.mandel
mandel_ctypes.argtypes = [ctypes.c_float, ctypes.c_float, ctypes.c_int,
ctypes.POINTER(ctypes.c_uint8)]


if __name__ == "__main__":
from timeit import default_timer as timer
from PIL import Image
from create_fractal import create_fractal
s = timer()
create_fractal_ctypes(ctypesimg, 20)
e = timer()
ctypes_onecall = e - s
print('ctypes calling create_fractal required {:.2f} millisecs'.format(1000*ctypes_onecall))
data = ctypesimg.asmemoryview()
print(max(data))
im = Image.frombuffer("L", (width, height), data, 'raw', 'L', 0, 1)
im.save('ctypes_fractal.png')

value = (ctypes.c_uint8*1)()
s = timer()
create_fractal(ctypesimg, 20, mandel_ctypes, value)
e = timer()
ctypes_createfractal = e - s
data = ctypesimg.asmemoryview()
print(max(data))
print('ctypes calling mandel required {:.2f} millisecs'.format(1000*ctypes_createfractal))
im = Image.frombuffer("L", (width, height), data, 'raw', 'L', 0, 1)
im.save('ctypes_mandel.png')
284 changes: 141 additions & 143 deletions pycon2017_cffi.ipynb

Large diffs are not rendered by default.

0 comments on commit c89e55e

Please sign in to comment.