|
6 | 6 | "source": [ |
7 | 7 | "# Using `jit`\n", |
8 | 8 | "\n", |
9 | | - "We know how to find hotspots now, how do we improve their performance?\n", |
10 | | - "\n", |
11 | | - "We `jit` them!\n", |
12 | | - "\n", |
13 | 9 | "We'll start with a trivial example but get to some more realistic applications shortly." |
14 | 10 | ] |
15 | 11 | }, |
|
24 | 20 | }, |
25 | 21 | { |
26 | 22 | "cell_type": "code", |
27 | | - "execution_count": null, |
| 23 | + "execution_count": 1, |
28 | 24 | "metadata": { |
29 | 25 | "collapsed": true |
30 | 26 | }, |
|
44 | 40 | }, |
45 | 41 | { |
46 | 42 | "cell_type": "code", |
47 | | - "execution_count": null, |
| 43 | + "execution_count": 2, |
48 | 44 | "metadata": { |
49 | 45 | "collapsed": true |
50 | 46 | }, |
|
55 | 51 | }, |
56 | 52 | { |
57 | 53 | "cell_type": "code", |
58 | | - "execution_count": null, |
| 54 | + "execution_count": 3, |
59 | 55 | "metadata": { |
60 | 56 | "collapsed": false |
61 | 57 | }, |
|
66 | 62 | }, |
67 | 63 | { |
68 | 64 | "cell_type": "code", |
69 | | - "execution_count": null, |
| 65 | + "execution_count": 4, |
70 | 66 | "metadata": { |
71 | 67 | "collapsed": false |
72 | 68 | }, |
73 | | - "outputs": [], |
| 69 | + "outputs": [ |
| 70 | + { |
| 71 | + "data": { |
| 72 | + "text/plain": [ |
| 73 | + "45041.071854295071" |
| 74 | + ] |
| 75 | + }, |
| 76 | + "execution_count": 4, |
| 77 | + "metadata": {}, |
| 78 | + "output_type": "execute_result" |
| 79 | + } |
| 80 | + ], |
74 | 81 | "source": [ |
75 | 82 | "sum_array(arr)" |
76 | 83 | ] |
77 | 84 | }, |
78 | 85 | { |
79 | 86 | "cell_type": "code", |
80 | | - "execution_count": null, |
| 87 | + "execution_count": 5, |
81 | 88 | "metadata": { |
82 | 89 | "collapsed": false |
83 | 90 | }, |
84 | | - "outputs": [], |
| 91 | + "outputs": [ |
| 92 | + { |
| 93 | + "name": "stdout", |
| 94 | + "output_type": "stream", |
| 95 | + "text": [ |
| 96 | + "10 loops, best of 3: 20.5 ms per loop\n" |
| 97 | + ] |
| 98 | + } |
| 99 | + ], |
85 | 100 | "source": [ |
86 | 101 | "plain = %timeit -o sum_array(arr)" |
87 | 102 | ] |
|
95 | 110 | }, |
96 | 111 | { |
97 | 112 | "cell_type": "code", |
98 | | - "execution_count": null, |
| 113 | + "execution_count": 6, |
99 | 114 | "metadata": { |
100 | 115 | "collapsed": true |
101 | 116 | }, |
|
113 | 128 | }, |
114 | 129 | { |
115 | 130 | "cell_type": "code", |
116 | | - "execution_count": null, |
| 131 | + "execution_count": 7, |
117 | 132 | "metadata": { |
118 | 133 | "collapsed": true |
119 | 134 | }, |
|
131 | 146 | }, |
132 | 147 | { |
133 | 148 | "cell_type": "code", |
134 | | - "execution_count": null, |
| 149 | + "execution_count": 8, |
135 | 150 | "metadata": { |
136 | 151 | "collapsed": false |
137 | 152 | }, |
138 | | - "outputs": [], |
| 153 | + "outputs": [ |
| 154 | + { |
| 155 | + "data": { |
| 156 | + "text/plain": [ |
| 157 | + "45041.07185429507" |
| 158 | + ] |
| 159 | + }, |
| 160 | + "execution_count": 8, |
| 161 | + "metadata": {}, |
| 162 | + "output_type": "execute_result" |
| 163 | + } |
| 164 | + ], |
139 | 165 | "source": [ |
140 | 166 | "sum_array_numba(arr)" |
141 | 167 | ] |
142 | 168 | }, |
143 | 169 | { |
144 | 170 | "cell_type": "code", |
145 | | - "execution_count": null, |
| 171 | + "execution_count": 9, |
146 | 172 | "metadata": { |
147 | 173 | "collapsed": false |
148 | 174 | }, |
149 | | - "outputs": [], |
| 175 | + "outputs": [ |
| 176 | + { |
| 177 | + "name": "stdout", |
| 178 | + "output_type": "stream", |
| 179 | + "text": [ |
| 180 | + "10000 loops, best of 3: 86.2 µs per loop\n" |
| 181 | + ] |
| 182 | + } |
| 183 | + ], |
150 | 184 | "source": [ |
151 | 185 | "jitted = %timeit -o sum_array_numba(arr)" |
152 | 186 | ] |
153 | 187 | }, |
154 | 188 | { |
155 | 189 | "cell_type": "code", |
156 | | - "execution_count": null, |
| 190 | + "execution_count": 10, |
157 | 191 | "metadata": { |
158 | 192 | "collapsed": false |
159 | 193 | }, |
160 | | - "outputs": [], |
| 194 | + "outputs": [ |
| 195 | + { |
| 196 | + "data": { |
| 197 | + "text/plain": [ |
| 198 | + "238.1571011913437" |
| 199 | + ] |
| 200 | + }, |
| 201 | + "execution_count": 10, |
| 202 | + "metadata": {}, |
| 203 | + "output_type": "execute_result" |
| 204 | + } |
| 205 | + ], |
161 | 206 | "source": [ |
162 | 207 | "plain.best / jitted.best" |
163 | 208 | ] |
|
171 | 216 | }, |
172 | 217 | { |
173 | 218 | "cell_type": "code", |
174 | | - "execution_count": null, |
| 219 | + "execution_count": 11, |
175 | 220 | "metadata": { |
176 | 221 | "collapsed": true |
177 | 222 | }, |
|
191 | 236 | }, |
192 | 237 | { |
193 | 238 | "cell_type": "code", |
194 | | - "execution_count": null, |
| 239 | + "execution_count": 12, |
195 | 240 | "metadata": { |
196 | 241 | "collapsed": false |
197 | 242 | }, |
198 | | - "outputs": [], |
| 243 | + "outputs": [ |
| 244 | + { |
| 245 | + "data": { |
| 246 | + "text/plain": [ |
| 247 | + "45041.07185429507" |
| 248 | + ] |
| 249 | + }, |
| 250 | + "execution_count": 12, |
| 251 | + "metadata": {}, |
| 252 | + "output_type": "execute_result" |
| 253 | + } |
| 254 | + ], |
199 | 255 | "source": [ |
200 | 256 | "sum_array(arr)" |
201 | 257 | ] |
202 | 258 | }, |
203 | 259 | { |
204 | 260 | "cell_type": "code", |
205 | | - "execution_count": null, |
| 261 | + "execution_count": 13, |
206 | 262 | "metadata": { |
207 | 263 | "collapsed": false |
208 | 264 | }, |
209 | | - "outputs": [], |
| 265 | + "outputs": [ |
| 266 | + { |
| 267 | + "name": "stdout", |
| 268 | + "output_type": "stream", |
| 269 | + "text": [ |
| 270 | + "10000 loops, best of 3: 89.1 µs per loop\n" |
| 271 | + ] |
| 272 | + } |
| 273 | + ], |
210 | 274 | "source": [ |
211 | 275 | "%timeit sum_array(arr)" |
212 | 276 | ] |
|
220 | 284 | }, |
221 | 285 | { |
222 | 286 | "cell_type": "code", |
223 | | - "execution_count": null, |
| 287 | + "execution_count": 14, |
224 | 288 | "metadata": { |
225 | 289 | "collapsed": false |
226 | 290 | }, |
227 | | - "outputs": [], |
| 291 | + "outputs": [ |
| 292 | + { |
| 293 | + "name": "stdout", |
| 294 | + "output_type": "stream", |
| 295 | + "text": [ |
| 296 | + "The slowest run took 5.33 times longer than the fastest. This could mean that an intermediate result is being cached.\n", |
| 297 | + "10000 loops, best of 3: 40.7 µs per loop\n" |
| 298 | + ] |
| 299 | + } |
| 300 | + ], |
228 | 301 | "source": [ |
229 | 302 | "%timeit arr.sum()" |
230 | 303 | ] |
231 | 304 | }, |
| 305 | + { |
| 306 | + "cell_type": "markdown", |
| 307 | + "metadata": {}, |
| 308 | + "source": [ |
| 309 | + "## When is Numba faster than NumPy?\n", |
| 310 | + "\n", |
| 311 | + "When doing more complex things, or when using less common integer types, like int16:" |
| 312 | + ] |
| 313 | + }, |
| 314 | + { |
| 315 | + "cell_type": "code", |
| 316 | + "execution_count": 15, |
| 317 | + "metadata": { |
| 318 | + "collapsed": false |
| 319 | + }, |
| 320 | + "outputs": [], |
| 321 | + "source": [ |
| 322 | + "arr_int16 = (arr * 4096).astype(numpy.int16)" |
| 323 | + ] |
| 324 | + }, |
| 325 | + { |
| 326 | + "cell_type": "code", |
| 327 | + "execution_count": 17, |
| 328 | + "metadata": { |
| 329 | + "collapsed": false |
| 330 | + }, |
| 331 | + "outputs": [ |
| 332 | + { |
| 333 | + "name": "stdout", |
| 334 | + "output_type": "stream", |
| 335 | + "text": [ |
| 336 | + "10000 loops, best of 3: 20 µs per loop\n" |
| 337 | + ] |
| 338 | + } |
| 339 | + ], |
| 340 | + "source": [ |
| 341 | + "jitted_int16 = %timeit -o sum_array_numba(arr_int16)" |
| 342 | + ] |
| 343 | + }, |
| 344 | + { |
| 345 | + "cell_type": "code", |
| 346 | + "execution_count": 18, |
| 347 | + "metadata": { |
| 348 | + "collapsed": false |
| 349 | + }, |
| 350 | + "outputs": [ |
| 351 | + { |
| 352 | + "name": "stdout", |
| 353 | + "output_type": "stream", |
| 354 | + "text": [ |
| 355 | + "The slowest run took 7.39 times longer than the fastest. This could mean that an intermediate result is being cached.\n", |
| 356 | + "10000 loops, best of 3: 108 µs per loop\n" |
| 357 | + ] |
| 358 | + } |
| 359 | + ], |
| 360 | + "source": [ |
| 361 | + "numpy_int16 = %timeit -o arr_int16.sum()" |
| 362 | + ] |
| 363 | + }, |
| 364 | + { |
| 365 | + "cell_type": "code", |
| 366 | + "execution_count": 19, |
| 367 | + "metadata": { |
| 368 | + "collapsed": false |
| 369 | + }, |
| 370 | + "outputs": [ |
| 371 | + { |
| 372 | + "data": { |
| 373 | + "text/plain": [ |
| 374 | + "5.420978311244756" |
| 375 | + ] |
| 376 | + }, |
| 377 | + "execution_count": 19, |
| 378 | + "metadata": {}, |
| 379 | + "output_type": "execute_result" |
| 380 | + } |
| 381 | + ], |
| 382 | + "source": [ |
| 383 | + "numpy_int16.best / jitted_int16.best" |
| 384 | + ] |
| 385 | + }, |
| 386 | + { |
| 387 | + "cell_type": "markdown", |
| 388 | + "metadata": {}, |
| 389 | + "source": [ |
| 390 | + "NumPy doesn't have a specialized version of `sum()` for 16-bit integers, but Numba just generated one that was many times faster! Numba can take advantage of things like AVX support for packed integers while NumPy has to cast to a larger datatype to use one of the precompiled implementations." |
| 391 | + ] |
| 392 | + }, |
232 | 393 | { |
233 | 394 | "cell_type": "markdown", |
234 | 395 | "metadata": {}, |
|
245 | 406 | } |
246 | 407 | ], |
247 | 408 | "metadata": { |
| 409 | + "anaconda-cloud": {}, |
248 | 410 | "kernelspec": { |
249 | 411 | "display_name": "Python [conda env:python3]", |
250 | 412 | "language": "python", |
|
0 commit comments