Skip to content

Instantly share code, notes, and snippets.

@bjodah
Last active July 12, 2021 12:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bjodah/5301679 to your computer and use it in GitHub Desktop.
Save bjodah/5301679 to your computer and use it in GitHub Desktop.
Annotating .py file with pxd for generating fast c-code. Needs Cython 0.19-dev, tested with both Python 2.7 and Python 3.3 Execute by running e.g.: bash run_python.sh bash run_cython_working.sh bash run_cython_not_working.sh
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Mandelbrot example using cython
"""
# stdlib imports
import time
# external imports
import numpy as np
try:
from PIL import Image
use_pil = True
except ImportError:
use_pil = False
# local imports
import mandel
import mapper
NX, NY, DIST, NS = 800, 800, 2.0, 40
t0 = time.time() # time execution
out = np.empty((NY, NX), dtype=np.float64)
mapper.map_mandel(out, NX, NY, NS, DIST)
print('Execution time: {}'.format(time.time() - t0))
print('Sum of matrix: {}'.format(np.sum(out)))
if use_pil:
# Generate 256 level greyscale image of number of steps
out *= 255.0
img = Image.frombuffer('L', out.shape, out.astype(np.uint8), 'raw', 'L', 0, 1)
img.save('out.png', "PNG")
import cython
cdef class MandelPoint:
cdef double x, y
@cython.locals(x=cython.double, y=cython.double, i=cython.int)
cpdef steps_to_dist(self, double dist, int maxsteps)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class MandelPoint:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y
def steps_to_dist(self, dist, maxsteps):
x = self.x
y = self.y
for i in range(maxsteps):
if (x**2 + y**2)**0.5 > dist:
break
x = x**2 - y**2 + self.x
y = 2*x*y + self.y
return i
import cython
from mandel cimport MandelPoint
cimport numpy as np
@cython.locals(x=cython.double, y=cython.double, i=cython.int, j=cython.int)
cpdef map_mandel(np.ndarray[np.npy_float64, ndim = 2] out, int nx, int ny, int ns, double dist)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
from itertools import product
from mandel import MandelPoint
def map_mandel(out, nx, ny, ns, dist):
"""
calc on grid with size 2*dist by 2*dist
"""
for i, j in product(range(nx), range(ny)):
x = (i - nx // 2) / (nx // 2) * dist
y = (j - ny // 2) / (ny // 2) * dist
out[j, i] = MandelPoint(x, y).steps_to_dist(dist, ns) / ns
#!/bin/bash
# Run script, using cython for "mandel.py+mandel.pxd"
# and "mapper.py+mapper.pxd" (_NOT_ working)
if [[ -f "mandel.c" ]]; then
rm mandel.c
fi
if [[ -f "mapper.c" ]]; then
rm mapper.c
fi
if [[ -f "setup.py" ]]; then
rm setup.py
fi
cp setup.py_pxd_both setup.py
python setup.py build_ext --inplace
if [[ $? -eq 0 ]]; then
mv mandel.py _mandel.py
mv mapper.py _mapper.py
python main.py
mv _mandel.py mandel.py
mv _mapper.py mapper.py
fi
if [[ $? -eq 0 && -f "out.png" ]]; then
eog out.png
fi
#!/bin/bash
# Run script, using cython for "mandel.py+mandel.pxd" (working)
if [[ -f "mandel.c" ]]; then
rm mandel.c
fi
if [[ -f "mapper.c" ]]; then
rm mapper.c
fi
if [[ -f "setup.py" ]]; then
rm setup.py
fi
cp setup.py_pxd_mandel setup.py
python setup.py build_ext --inplace
if [[ $? -eq 0 ]]; then
mv mandel.py _mandel.py
python main.py
mv _mandel.py mandel.py
fi
if [[ $? -eq 0 && -f "out.png" ]]; then
eog out.png
fi
#!/bin/bash
# Run script, not using cython (working)
rm mandel.*so
rm mapper.*so
python main.py
if [[ $? -eq 0 && -f "out.png" ]]; then
eog out.png
fi
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(ext_modules = [
Extension('mandel', ['mandel.py', 'mandel.pxd']),
Extension('mapper', ['mapper.py', 'mapper.pxd']),
],
cmdclass = {'build_ext': build_ext}
)
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(ext_modules = [
Extension('mandel', ['mandel.py', 'mandel.pxd']),
],
cmdclass = {'build_ext': build_ext}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment