Skip to content

Commit c89e55e

Browse files
committed
fix bugs, add fractal_ctypes.py
1 parent c2df8df commit c89e55e

File tree

3 files changed

+234
-164
lines changed

3 files changed

+234
-164
lines changed

create_fractal.py

+19-21
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
1-
#And for desert:
2-
import sys
3-
print(sys.executable)
4-
from timeit import default_timer as timer
5-
import cffi
6-
from PIL import Image
7-
8-
ffi = cffi.FFI()
1+
from __future__ import print_function, division
92

103
class Img(object):
114
def __init__(self, width, height):
125
self.width = width
136
self.height = height
14-
self.data = ffi.new('uint8_t[%d]' % (width*height,))
7+
self.data = bytearray(width*height)
158

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

48-
# Pure python
49-
width = 1500
50-
height = 1000
51-
image = Img(width, height)
52-
s = timer()
53-
oneval = ffi.new('uint8_t[1]')
54-
create_fractal(image, 20, mandel, oneval)
55-
e = timer()
56-
pure_pypy = e - s
57-
print('pure pypy required {:.2f} millisecs'.format(pure_pypy))
58-
im = Image.fromarray(image.data.reshape(height, width))
59-
im.save('pypyy.png')
41+
if __name__ == '__main__':
42+
from timeit import default_timer as timer
43+
from PIL import Image
44+
# Pure python
45+
width = 1500
46+
height = 1000
47+
image = Img(width, height)
48+
s = timer()
49+
oneval = bytearray(1)
50+
create_fractal(image, 20, mandel, oneval)
51+
e = timer()
52+
elapsed = e - s
53+
import platform
54+
imp = platform.python_implementation().lower()
55+
print('pure {} required {:.2f} millisecs'.format(imp, 1000*elapsed))
56+
im = Image.frombuffer("L", (width, height), image.data, "raw", "L", 0, 1)
57+
im.save('{}.png'.format(imp))

fractal_ctypes.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from __future__ import print_function, division
2+
import subprocess
3+
import os
4+
5+
width = 1500
6+
height = 1000
7+
#ctypes
8+
# First all the declarations. Each function and struct must be redefined ...
9+
import ctypes
10+
11+
class CtypesImg(ctypes.Structure):
12+
_fields_ = [('width', ctypes.c_int),
13+
('height', ctypes.c_int),
14+
('data', ctypes.POINTER(ctypes.c_uint8)), # HUH?
15+
]
16+
array_cache = {}
17+
def __init__(self, width, height):
18+
self.width = width
19+
self.height = height
20+
# Create a class type to hold the data.
21+
# Since this creates a type, cache it for reuse rather
22+
# than create a new one each time
23+
if width*height not in self.array_cache:
24+
self.array_cache[width*height] = ctypes.c_uint8 * (width * height)
25+
# Note this keeps the img.data alive in the interpreter
26+
self.data = self.array_cache[width*height]() # !!!!!!
27+
28+
def asmemoryview(self):
29+
# There must be a better way, but this code will not
30+
# be timed, so explicit trumps implicit
31+
ret = self.array_cache[width*height]()
32+
for i in range(width*height):
33+
ret[i] = self.data[i]
34+
return ret
35+
36+
ctypesimg = CtypesImg(width, height)
37+
38+
39+
# Load the DLL
40+
cdll = ctypes.cdll.LoadLibrary('./libcreate_fractal.so')
41+
42+
#Fish the function pointers from the DLL and define the interfaces
43+
create_fractal_ctypes = cdll.create_fractal
44+
create_fractal_ctypes.argtypes = [CtypesImg, ctypes.c_int]
45+
46+
mandel_ctypes = cdll.mandel
47+
mandel_ctypes.argtypes = [ctypes.c_float, ctypes.c_float, ctypes.c_int,
48+
ctypes.POINTER(ctypes.c_uint8)]
49+
50+
51+
if __name__ == "__main__":
52+
from timeit import default_timer as timer
53+
from PIL import Image
54+
from create_fractal import create_fractal
55+
s = timer()
56+
create_fractal_ctypes(ctypesimg, 20)
57+
e = timer()
58+
ctypes_onecall = e - s
59+
print('ctypes calling create_fractal required {:.2f} millisecs'.format(1000*ctypes_onecall))
60+
data = ctypesimg.asmemoryview()
61+
print(max(data))
62+
im = Image.frombuffer("L", (width, height), data, 'raw', 'L', 0, 1)
63+
im.save('ctypes_fractal.png')
64+
65+
value = (ctypes.c_uint8*1)()
66+
s = timer()
67+
create_fractal(ctypesimg, 20, mandel_ctypes, value)
68+
e = timer()
69+
ctypes_createfractal = e - s
70+
data = ctypesimg.asmemoryview()
71+
print(max(data))
72+
print('ctypes calling mandel required {:.2f} millisecs'.format(1000*ctypes_createfractal))
73+
im = Image.frombuffer("L", (width, height), data, 'raw', 'L', 0, 1)
74+
im.save('ctypes_mandel.png')

pycon2017_cffi.ipynb

+141-143
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)