Skip to content

Commit 481facc

Browse files
committed
#2 add lecture 2
1 parent 063eac7 commit 481facc

File tree

1 file changed

+193
-0
lines changed

1 file changed

+193
-0
lines changed
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {
6+
"slideshow": {
7+
"slide_type": "slide"
8+
}
9+
},
10+
"source": [
11+
"# Optimisation - Cython\n",
12+
"## Martin Robinson\n",
13+
"## Oct 2019"
14+
]
15+
},
16+
{
17+
"cell_type": "markdown",
18+
"metadata": {
19+
"slideshow": {
20+
"slide_type": "slide"
21+
}
22+
},
23+
"source": [
24+
"# Using lower-level languages\n",
25+
"\n",
26+
"- Interpreted languages are fundamentially speed-limited when they only consider *type* at run-time.\n",
27+
"- e.g. consider what happens with the types of the variables in the following function\n",
28+
"```python\n",
29+
"def norm(arg_list, p):\n",
30+
" sum = 0 # sum is an int here\n",
31+
" for x in arg_list: # type of x depends on input container\n",
32+
" sum += abs(x)**p # type of rhs depends on both x and p, sum could *change* type here\n",
33+
" return sum**(1.0/p) # return value is probably float due to 1.0\n",
34+
"```\n",
35+
"- how much memory to allocate for sum? does this memory need to be re-allocated during the loop? are conversion routines between types required during the loop?"
36+
]
37+
},
38+
{
39+
"cell_type": "markdown",
40+
"metadata": {
41+
"slideshow": {
42+
"slide_type": "slide"
43+
}
44+
},
45+
"source": [
46+
"- compare to equivilant C++ code\n",
47+
"```cpp\n",
48+
"float norm(std::vector<float>& arg_list, float p) {\n",
49+
" float sum = 0.0f;\n",
50+
" for (size_t i = 0; i < arg_list.size(); ++i) {\n",
51+
" sum += std::pow(std::abs(arg_list), p);\n",
52+
" }\n",
53+
" return std::pow(sum, 1.0f/p);\n",
54+
"}\n",
55+
"```\n",
56+
"- compiler can pre-allocate the stack size because the sizes of local variables known, no type conversions neccessary\n",
57+
"- compiler can generate efficient machine code because the programmer has provided more information (i.e. types)\n",
58+
" "
59+
]
60+
},
61+
{
62+
"cell_type": "markdown",
63+
"metadata": {},
64+
"source": [
65+
"# \"Compiling\" Python code\n",
66+
"\n",
67+
"- All python implementations (CPython, PyPy, IronPython) compile to *bytecode*, which is then either interpreted at run-time, or perhaps further compiled to native machine code\n",
68+
"- Implementations that compile to native machine code usually implement something close to normal python, but with restrictions or additions that alter the nature of the language. These include:\n",
69+
" - Cython (Python-to-C)\n",
70+
" - Nuitka (Python-to-C++)\n",
71+
" - Numba (Python-to-LLVM IR)"
72+
]
73+
},
74+
{
75+
"cell_type": "markdown",
76+
"metadata": {},
77+
"source": [
78+
"# \"Wrapping\" C and C++ for use in Python\n",
79+
"\n",
80+
"- the compilers in the previous slide implement an altered version of python, yet another language to learn!\n",
81+
"- If your already comfortable with C, C++ or Fortran, why not use this directly and write a *wrapper* to call from Python?\n",
82+
"- "
83+
]
84+
},
85+
{
86+
"cell_type": "markdown",
87+
"metadata": {},
88+
"source": [
89+
"# Cython"
90+
]
91+
},
92+
{
93+
"cell_type": "markdown",
94+
"metadata": {},
95+
"source": [
96+
"# Your first Cython program"
97+
]
98+
},
99+
{
100+
"cell_type": "code",
101+
"execution_count": null,
102+
"metadata": {},
103+
"outputs": [],
104+
"source": [
105+
"```python\n",
106+
"def norm(a, p):\n",
107+
" s = 0\n",
108+
" x_max = a.shape[0]\n",
109+
" y_max = a.shape[1]\n",
110+
" for i in range(x_max):\n",
111+
" for j in range(y_max):\n",
112+
" s += abs(a[i, j])**p\n",
113+
" return s**(1.0/p)\n",
114+
"\n",
115+
"```"
116+
]
117+
},
118+
{
119+
"cell_type": "markdown",
120+
"metadata": {},
121+
"source": [
122+
"# Manual compilation"
123+
]
124+
},
125+
{
126+
"cell_type": "markdown",
127+
"metadata": {},
128+
"source": [
129+
"# Examining the generated code"
130+
]
131+
},
132+
{
133+
"cell_type": "markdown",
134+
"metadata": {},
135+
"source": [
136+
"# Adding types"
137+
]
138+
},
139+
{
140+
"cell_type": "markdown",
141+
"metadata": {},
142+
"source": [
143+
"# memoryviews"
144+
]
145+
},
146+
{
147+
"cell_type": "markdown",
148+
"metadata": {},
149+
"source": [
150+
"# Tuning indexing further"
151+
]
152+
},
153+
{
154+
"cell_type": "code",
155+
"execution_count": null,
156+
"metadata": {},
157+
"outputs": [],
158+
"source": [
159+
"```python\n",
160+
"from libc.math cimport abs\n",
161+
"cimport cython\n",
162+
"\n",
163+
"@cython.boundscheck(False) # Deactivate bounds checking\n",
164+
"@cython.wraparound(False) # Deactivate negative indexing.\n",
165+
"@cython.cdivision(True) # Deactivate normal python division checking\n",
166+
"cdef double norm(double [:, :] a, int p):\n",
167+
" cdef double s = 0\n",
168+
" cdef Py_ssize_t x_max = a.shape[0]\n",
169+
" cdef Py_ssize_t y_max = a.shape[1]\n",
170+
" for i in range(x_max):\n",
171+
" for j in range(y_max):\n",
172+
" s += abs(a[i, j])**p\n",
173+
" return s**(1.0/p)\n",
174+
"```"
175+
]
176+
},
177+
{
178+
"cell_type": "markdown",
179+
"metadata": {},
180+
"source": [
181+
"# Packaging Cython programs"
182+
]
183+
}
184+
],
185+
"metadata": {
186+
"language_info": {
187+
"name": "python",
188+
"pygments_lexer": "ipython3"
189+
}
190+
},
191+
"nbformat": 4,
192+
"nbformat_minor": 2
193+
}

0 commit comments

Comments
 (0)