Skip to content

Commit

Permalink
create ctypes class type only once
Browse files Browse the repository at this point in the history
  • Loading branch information
mattip committed Jun 13, 2017
1 parent f8eb626 commit c2df8df
Showing 1 changed file with 45 additions and 19 deletions.
64 changes: 45 additions & 19 deletions pycon2017_cffi.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2086,10 +2086,8 @@
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": true
},
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"#ctypes\n",
Expand All @@ -2101,18 +2099,22 @@
" ('height', ctypes.c_int),\n",
" ('data', ctypes.POINTER(ctypes.c_uint8)), # HUH?\n",
" ]\n",
"\n",
" array_cache = {}\n",
" def __init__(self, width, height):\n",
" self.width = width\n",
" self.height = height\n",
" # Note this creates a class for each width*height value\n",
" # but will keep the img.data alive in the interpreter\n",
" self.data = (ctypes.c_uint8 * (width * height))() # !!!!!!\n",
" # Create a class type to hold the data.\n",
" # Since this creates a type, cache it for reuse rather\n",
" # than create a new one each time\n",
" if width*height not in self.array_cache:\n",
" self.array_cache[width*height] = ctypes.c_uint8 * (width * height)\n",
" # Note this keeps the img.data alive in the interpreter\n",
" self.data = self.array_cache[width*height]() # !!!!!!\n",
"\n",
" def asmemoryview(self):\n",
" # There must be a better way, but this code will not\n",
" # be timed, so explicit trumps implicit\n",
" ret = (ctypes.c_uint8 * (width * height))()\n",
" ret = self.data = self.array_cache[width*height]()\n",
" for i in range(width*height):\n",
" ret[i] = self.data[i]\n",
" return memoryview(ret)\n",
Expand All @@ -2128,7 +2130,8 @@
"create_fractal_ctypes.argtypes = [CtypesImg, ctypes.c_int]\n",
"\n",
"mandel_ctypes = cdll.mandel\n",
"mandel_ctypes.argtypes = [ctypes.c_float, ctypes.c_float, ctypes.c_int, ctypes.POINTER(ctypes.c_uint8)]"
"mandel_ctypes.argtypes = [ctypes.c_float, ctypes.c_float, ctypes.c_int, \n",
" ctypes.POINTER(ctypes.c_uint8)]"
]
},
{
Expand All @@ -2144,15 +2147,15 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ctypes calling create_fractal required 203.95 millisecs\n",
"ctypes calling mandel required 2604.29 millisecs\n"
"ctypes calling create_fractal required 197.33 millisecs\n",
"ctypes calling mandel required 2463.65 millisecs\n"
]
}
],
Expand Down Expand Up @@ -4592,7 +4595,8 @@
" unsigned char * data\n",
" \n",
" int create_fractal(cImg img, int iters);\n",
" int mandel(float real, float imag, int max_iters, unsigned char * val);\n",
" int mandel(float real, float imag, int max_iters,\n",
" unsigned char * val);\n",
" \n",
"def cython_create_fractal(pyimg, iters):\n",
" cdef cImg cimg\n",
Expand All @@ -4606,7 +4610,8 @@
" return create_fractal(cimg, citers)\n",
"\n",
"\n",
"cpdef int cython_mandel(float real, float imag, int max_iters, unsigned char[::1] val):\n",
"cpdef int cython_mandel(float real, float imag, int max_iters,\n",
" unsigned char[::1] val):\n",
" return mandel(real, imag, max_iters, &val[0])"
]
},
Expand Down Expand Up @@ -5463,7 +5468,9 @@
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
Expand All @@ -5479,7 +5486,8 @@
}
],
"source": [
"# Now let's try and work out who is the good, who the bad, and who the ugly\n",
"# Now let's try and work out who is the good, who the bad, \n",
"# and who the ugly\n",
"import pprint\n",
"pprint.pprint([[' ', 'CreateFractal in Python', 'CreateFractal in C'],\n",
" ['Python', '{:13.2f} millisecs'.format(1000*pure_python), '{:18s}'.format('')],\n",
Expand All @@ -5500,16 +5508,34 @@
" - What happens when the C code changes?\n",
"* Compiler dependency\n",
" - ctypes needs none, Cython requires one, CFFI can go either way\n",
"* Suseptability to bugs (object lifetimes, signature mismatches)\n",
"* Susceptability to bugs (object lifetimes, signature mismatches)\n",
" - All use a minilanguage for interfacing, only CFFI's is standard C\n",
" - Cython will handle most transformations automatically\n",
" - CFFI can be tricky for C-level pointers\n",
"* Speed and productivity\n",
" - Cython is heavily optimized, tightly integrated to the C-API\n",
" - If the headers are pure C, CFFI should be simple\n",
" - Projects exist to generate wrappers for all three\n",
"* Which technology is actively maintained (ctypes went into the stdlib to die?)\n",
"* Which technology is actively maintained (ctypes went into the stdlib to die?)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" --- \n",
" --- \n",
" --- \n",
" --- \n",
" \n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And now the pop-quiz. If we run the pure python version in PyPy what time will we get?:\n",
"\n",
"* Around a 2X speed up\n",
Expand Down

0 comments on commit c2df8df

Please sign in to comment.