In [1]:
# It seems that, for now, Azure Notebook does not support '.pyx' file compiling-and-importing.
In [ ]:
# OK! After reading the documention, I find how to use Cython in notebook: magic command %%cython
In [1]:
%load_ext Cython
In [2]:
%%cython
import numpy as np
cimport numpy as np
DTYPE = np.int
ctypedef np.int_t DTYPE_t
# cimport cython
# @cython.boundscheck(False)
# @cython.wraparound(False)
def naive_con1(np.ndarray f, np.ndarray g):
if g.shape[0] % 2 != 1 and f.shape[0] % 2 != 1:
raise ValueError("Only odd dimensions on filter supported!")
assert f.dtype == DTYPE and g.dtype == DTYPE
cdef int vmax = f.shape[0]
cdef int wmax = f.shape[1]
cdef int smax = g.shape[0]
cdef int tmax = g.shape[1]
cdef int smid = smax // 2
cdef int tmid = tmax // 2
cdef int xmax = vmax + 2*smid
cdef int ymax = wmax + 2*tmid
cdef np.ndarray h = np.zeros([xmax, ymax], dtype=DTYPE)
cdef int x, y, s, t, v, w
cdef int s_from, s_to, t_from, t_to
cdef DTYPE_t value
# Do convolution
for x in range(xmax):
for y in range(ymax):
# Calculate pixel value for h at (x,y). Sum one component
# for each pixel (s, t) of the filter g.
s_from = max(smid - x, -smid)
s_to = min((xmax - x) - smid, smid + 1)
t_from = max(tmid - y, -tmid)
t_to = min((ymax - y) - tmid, tmid + 1)
value = 0
for s in range(s_from, s_to):
for t in range(t_from, t_to):
v = x - smid + s
w = y - tmid + t
value += g[smid - s, tmid - t] * f[v, w]
h[x, y] = value
return h
In [3]:
%%cython
import numpy as np
cimport numpy as np
DTYPE = np.int
ctypedef np.int_t DTYPE_t
# cimport cython
# @cython.boundscheck(False)
# @cython.wraparound(False)
def naive_con2(np.ndarray[DTYPE_t, ndim=2] f, np.ndarray[DTYPE_t, ndim=2] g):
if g.shape[0] % 2 != 1 and f.shape[0] % 2 != 1:
raise ValueError("Only odd dimensions on filter supported!")
assert f.dtype == DTYPE and g.dtype == DTYPE
cdef int vmax = f.shape[0]
cdef int wmax = f.shape[1]
cdef int smax = g.shape[0]
cdef int tmax = g.shape[1]
cdef int smid = smax // 2
cdef int tmid = tmax // 2
cdef int xmax = vmax + 2*smid
cdef int ymax = wmax + 2*tmid
cdef np.ndarray[DTYPE_t, ndim=2] h = np.zeros([xmax, ymax], dtype=DTYPE)
cdef int x, y, s, t, v, w
cdef int s_from, s_to, t_from, t_to
cdef DTYPE_t value
# Do convolution
for x in range(xmax):
for y in range(ymax):
# Calculate pixel value for h at (x,y). Sum one component
# for each pixel (s, t) of the filter g.
s_from = max(smid - x, -smid)
s_to = min((xmax - x) - smid, smid + 1)
t_from = max(tmid - y, -tmid)
t_to = min((ymax - y) - tmid, tmid + 1)
value = 0
for s in range(s_from, s_to):
for t in range(t_from, t_to):
v = x - smid + s
w = y - tmid + t
value += g[smid - s, tmid - t] * f[v, w]
h[x, y] = value
return h
In [4]:
%%cython
import numpy as np
cimport numpy as np
DTYPE = np.int
ctypedef np.int_t DTYPE_t
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
def naive_con3(np.ndarray[DTYPE_t, ndim=2] f, np.ndarray[DTYPE_t, ndim=2] g):
if g.shape[0] % 2 != 1 and f.shape[0] % 2 != 1:
raise ValueError("Only odd dimensions on filter supported!")
assert f.dtype == DTYPE and g.dtype == DTYPE
cdef int vmax = f.shape[0]
cdef int wmax = f.shape[1]
cdef int smax = g.shape[0]
cdef int tmax = g.shape[1]
cdef int smid = smax // 2
cdef int tmid = tmax // 2
cdef int xmax = vmax + 2*smid
cdef int ymax = wmax + 2*tmid
cdef np.ndarray[DTYPE_t, ndim=2] h = np.zeros([xmax, ymax], dtype=DTYPE)
cdef int x, y, s, t, v, w
cdef int s_from, s_to, t_from, t_to
cdef DTYPE_t value
# Do convolution
for x in range(xmax):
for y in range(ymax):
# Calculate pixel value for h at (x,y). Sum one component
# for each pixel (s, t) of the filter g.
s_from = max(smid - x, -smid)
s_to = min((xmax - x) - smid, smid + 1)
t_from = max(tmid - y, -tmid)
t_to = min((ymax - y) - tmid, tmid + 1)
value = 0
for s in range(s_from, s_to):
for t in range(t_from, t_to):
v = x - smid + s
w = y - tmid + t
value += g[smid - s, tmid - t] * f[v, w]
h[x, y] = value
return h
In [5]:
import numpy as np
N = 300
f = np.arange(N*N, dtype=np.int).reshape((N, N))
g = np.arange(9*9, dtype=np.int).reshape((9, 9))
In [6]:
%timeit -n3 -r3 naive_con1(f, g)
In [7]:
%timeit -n3 -r3 naive_con2(f, g)
In [8]:
%timeit -n3 -r3 naive_con3(f, g)