======================================== Exercises for Memory-Efficient Computing ======================================== In-memory computations: Numexpr as an accelerator of NumPy expressions ====================================================================== Initially, we are going to see how to optimize the computation of expressions that fit well in main memory. For the exercises in this sections we will mainly use the ``poly1.py`` script. 1. Use script ``poly1.py`` to check how much time it takes to evaluate the next polynomial:: y = .25*x**3 + .75*x**2 - 1.5*x - 2 with x in the range [-1, 1], and with 10 millions points. - Set the `what` parameter to "numexpr" (or pass it in command line) and take note of the speed-up versus the "numpy" case. Why do you think the speed-up is so large? 2. The expression below:: y = ((.25*x + .75)*x - 1.5)*x - 2 represents the same polynomial than the original one, but with some interesting side-effects in efficiency. Repeat the computation using this expression with both numpy and numexpr and get your own conclusions. - Why do you think numpy is performing much more efficiently with this new expression? - Why the speed-up in numexpr is not so high in comparison? - Why numexpr continues to be faster than numpy? Out-of-memory computations: ``numpy.memmap`` versus ``tables.Expr`` =================================================================== Now, we are going to make use of the script ``poly2.py`` to compute the same problem than above, but using an out-of-memory paradigm. Comparing ``numpy.memmap`` and ``tables.Expr`` approaches --------------------------------------------------------- 3. Use script ``poly2.py`` to study the `compute_numpy` and `compute_tables` functions and try to understand how the different ``numpy.memmap`` and ``tables.Expr`` paradigms work. - Compare the times for computing the polynomial via both ``numpy.memmap`` and ``tables.Expr`` (set the `what` variable properly, or pass the string as first argument). Why the difference in speed between both approaches is so large? - Compare the latter times with the times for the in-memory approach. Why do you think the out-of-memory paradigm is slower? Playing with compression ------------------------ 4. With the ``tables.Expr`` module, play with different compression levels (including 0, i.e. no compression) for the Blosc compressor. - Which one compresses better? - Which one achieves the best compression/time ratio? - Is this mode competitive in terms of speed with the non-compressed mode? 5. Compare 'blosc' with other compressors in PyTables, like 'zlib' or 'lzo'. - Which one compresses better? - Which one achieves the best compression/time ratio? Making real "out-of-memory" computations ---------------------------------------- Of course, the advantage of the out-of-memory approach is that you can still perform your computations even if they exceed your available memory. 6. Set the number of elements in N to some value that slightly exceeds the amount of the *physical* memory in your laptop, but still, less than the *virtual* memory. **Hint**: the working set for this problem is 2*N*size(datatype). As the datatype is a double precision one, size(datatype)=8. So, for a laptop with 1 GB of main memory, setting N=80 millions is fine. **Warning**: For this part, you should make sure that you have some swap space available (check with `free` command on Linux). If you don't, please create one. - Which approach (``numpy.memmap`` or ``tables.Expr``) is faster?