{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Parallel Computing with IPython\n", "\n", "Today we'll look at performing parallel computations with IPython. Much of this material will draw from resources available online, including\n", "\n", "- The IPython [Parallel documentation](http://ipython.org/ipython-doc/rel-1.1.0/parallel/parallel_intro.html)\n", "- Min RK's [IPython Parallel Tutorial](https://github.com/minrk/IPython.parallel.tutorial.git) (the source for much of this lecture)\n", "\n", "Parallel computing is generally very difficult, and IPython provides primitives for a number of scenarios, including:\n", "\n", "- Single program, multiple data (SPMD) parallelism\n", "- Multiple program, multiple data (MPMD) parallelism\n", "- Task farming\n", "- Data parallel computation\n", "- Coordination of distributed processes\n", "- Combinations of these approaches\n", "- Custom user defined approaches\n", "\n", "\n", "In addition, IPython parallel includes tools for executing parallel jobs *interactively* (this is the \"I\" in \"IPython\")." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## First... Why IPython Parallel?\n", "\n", "One common complaint levied against IPython is that it's too bloated. Why does a project which started as an enhanced Python interpreter include Parallel tools? You can hear the answer from IPython's creators in [This Scipy 2012 Keynote](http://pyvideo.org/video/1221/ipython-tools-for-the-entire-lifecycle-of-resear). In it, Fernando Perez says IPython is\n", "\n", "> *\"A tool for managing the entire lifecycle of a scientific idea\"*\n", "\n", "\n", "This life-cycle includes the following:\n", "\n", "- Individual exploratory work\n", "- Collaborative development\n", "- Production work (HPC, cloud, parallel computing)\n", "- Publication\n", "- Education\n", "\n", "Within this context, you can see how the IPython interpreter, parallel tools, and the notebook all fit the vision.\n", "\n", "Additionally, it is a natural fit because the underlying message-passing architecture necessary for the IPython notebook is also a natural platform for parallel computing." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## IPython Parallel Architecture\n", "\n", "\n", "The IPython architecture consists of four components:\n", "\n", "- The IPython engine\n", "- The IPython hub\n", "- The IPython schedulers\n", "- The cluster client\n", "\n", "These components live in the `IPython.parallel` package and are\n", "installed with IPython." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### IPython engine\n", "\n", "The IPython engine is a **Python kernel which takes commands over a network connection**. There is one engine per core.\n", "\n", "An important property of an IPython engine is that it blocks while user code is being executed, which allows asynchronous execution.\n", "\n", "### IPython controller\n", "\n", "\n", "The IPython controller **provides an interface for working with a\n", "set of engines.**\n", "\n", "At a general level, the controller is a collection of\n", "processes to which IPython engines and clients can connect. The\n", "controller is composed of a `Hub` and a collection of\n", "`Schedulers`, which may be in processes or threads.\n", "\n", "The controller provides a single point of contact for users who\n", "wish to utilize the engines in the cluster. There is a variety of\n", "different ways of working with a controller, but all of these\n", "models are implemented via the `View.apply` method, after\n", "constructing `View` objects to represent different collections engines.\n", "The two primary models for interacting with engines are:\n", "\n", "- A **Direct** interface, where engines are addressed explicitly.\n", "- A **LoadBalanced** interface, where the Scheduler is trusted with\n", " assigning work to appropriate engines.\n", "\n", "Advanced users can readily extend the View models to enable other styles\n", "of parallelism.\n", "\n", "#### The Hub\n", "The center of an IPython cluster is the Hub. The Hub can be viewed as an \u00fcber-logger, which keeps track of engine connections, schedulers, clients, as well as persist all\n", "task requests and results in a database for later use.\n", "\n", "\n", "#### Schedulers\n", "All actions that can be performed on the engine go through a Scheduler.\n", "While the engines themselves block when user code is run, the schedulers\n", "hide that from the user to provide a fully asynchronous interface to a\n", "set of engines. Each Scheduler is a small GIL-less function in C provided\n", "by pyzmq (the Python load-balanced scheduler being an exception). " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Getting Started\n", "\n", "The first thing required for using IPython Parallel is to start the cluster. By default, this will start a local cluster on your own computer, utilizing your CPU's multiple cores if available.\n", "\n", "There are two ways to do this.\n", "\n", "### From the command-line\n", "On the command-line, you can run the following command to start an IPython cluster:\n", "\n", " [~]$ ipcluster start -n 4\n", " \n", "will start a cluster with 4 cores (probably what you have available on a modern laptop). To use as many cores as are available, leave out the ``n``:\n", "\n", " [~]$ ipcluster start\n", " \n", "This spins-up a Python kernel on each core, along with a hub that connects to them.\n", "\n", "### From the notebook interface\n", "Within the IPython notebook, you can use the *Clusters* tab of the dashboard, and press *Start* with the desired number of cores, under the desired profile (more on profiles later). This will automatically run the correct commands to start your IPython cluster." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Accessing the Clients\n", "\n", "To make sure everything is working, let's run a simple example. We'll use the ``IPython.parallel`` submodule to get a view of the clients, and print the client ids:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from IPython import parallel\n", "clients = parallel.Client()\n", "clients.block = True # use synchronous computations\n", "print clients.ids" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[0, 1, 2, 3]\n" ] } ], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can use this object to run some code. Let's define a simple function that we will execute on the cores:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def mul(a, b):\n", " return a * b\n", "\n", "mul(5, 6)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 2, "text": [ "30" ] } ], "prompt_number": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's execute ``mul`` on the first engine:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "clients[0].apply(mul, 5, 6)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 3, "text": [ "30" ] } ], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the *function* becomes the first argument of ``apply``, and any\n", "additional arguments or keyword arguments are passed after it.\n", "\n", "We can similarly execute ``mul`` in parallel on all the engines at once:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "clients[:].apply(mul, 5, 6)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 4, "text": [ "[30, 30, 30, 30]" ] } ], "prompt_number": 4 }, { "cell_type": "markdown", "metadata": {}, "source": [ "But say we want to pass different arguments to each instance of ``mul``. In normal Python, we could do this with the ``map()`` function:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "map(mul, [5, 6, 7, 8], [8, 9, 10, 11])" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 5, "text": [ "[40, 54, 70, 88]" ] } ], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The client views also have a map function which does the execution in parallel. Let's use a load-balanced view so that the IPython scheduler takes care of farming the tasks for us:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "view = clients.load_balanced_view()\n", "view.map(mul, [5, 6, 7, 8], [8, 9, 10, 11])" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 6, "text": [ "[40, 54, 70, 88]" ] } ], "prompt_number": 6 }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is the basic interface to parallel computation in IPython!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Concepts\n", "\n", "### The Client\n", "The client is a lightweight handle on all the engines of a cluster:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "clients = parallel.Client(profile='default')\n", "print len(clients)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "4\n" ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Views\n", "Views provide the fundamental ways of accessing the clients. There are two types of views:\n", "\n", "#### Direct View\n", "A direct view allows direct execution of a command on *all* the engines:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "clients.block = True\n", "dview = clients.direct_view()\n", "dview.block = True\n", "print dview" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "\n" ] } ], "prompt_number": 8 }, { "cell_type": "code", "collapsed": false, "input": [ "dview.apply(sum, [1, 2, 3])" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 9, "text": [ "[6, 6, 6, 6]" ] } ], "prompt_number": 9 }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also obtain a Direct view by slicing the ``Clients`` object:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "clients[::2]" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 10, "text": [ "" ] } ], "prompt_number": 10 }, { "cell_type": "code", "collapsed": false, "input": [ "clients[::2].apply(sum, [1, 2, 3])" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 11, "text": [ "[6, 6]" ] } ], "prompt_number": 11 }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Load Balanced View\n", "\n", "A load balanced view allows execution of a command on *any one* engine. Which engine is used is up to the scheduler:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "lview = clients.load_balanced_view()\n", "print lview" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "\n" ] } ], "prompt_number": 12 }, { "cell_type": "code", "collapsed": false, "input": [ "lview.apply(sum, [1, 2, 3])" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 13, "text": [ "6" ] } ], "prompt_number": 13 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Introspection: looking at the Process ID\n", "\n", "One way to introspect what's going on is to get the Process ID of the engines.\n", "This gives a unique label of any running process on your computer. If you have\n", "a cluster running on multiple computers, you can also print the hostname to see\n", "which host each cluster is running on:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import os\n", "import socket\n", "print os.getpid()\n", "print socket.gethostname()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "9146\n", "jakesmac\n" ] } ], "prompt_number": 14 }, { "cell_type": "code", "collapsed": false, "input": [ "dview.apply(os.getpid)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 15, "text": [ "[9142, 9143, 9144, 9145]" ] } ], "prompt_number": 15 }, { "cell_type": "code", "collapsed": false, "input": [ "for i in range(5):\n", " print lview.apply(os.getpid)" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "9145\n", "9144\n", "9142\n", "9143\n", "9145\n" ] } ], "prompt_number": 16 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the load-balanced view chooses engines somewhat randomly (it's not actually random, but is based on a process which is opaque to the user)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Working with Direct Views:\n", "\n", "The direct view is an interface in which **each engine is directly exposed to the user**.\n", "\n", "The direct view is a very flexible wrapper of the client. Let's look at a few ways of managing remote execution and remote data with direct views. We'll look at the following:\n", "\n", "- Blocking vs. non-blocking execution\n", "- Ways to manage remote execution\n", "- Ways to manage & access remote data" ] }, { "cell_type": "code", "collapsed": false, "input": [ "clients = parallel.Client()\n", "dview = clients[:]" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 17 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### DirectView: blocking vs. non-blocking\n", "\n", "In a DirectView interface, we can either use **Blocking** (synchronous) execution, in which all results must finish computing before any results are recorded, or **non-blocking** (asynchronous) execution, where we receive results as they finish.\n", "\n", "Here's an example of the two:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def get_pid_slowly():\n", " # imports in the function, otherwise these imports\n", " # don't happen on the engines\n", " import os\n", " import time\n", " import random\n", " \n", " # sleep up to 10 seconds\n", " time.sleep(10 * random.random())\n", " return os.getpid()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 18 }, { "cell_type": "code", "collapsed": false, "input": [ "dview.block = True\n", "dview.apply(get_pid_slowly)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 19, "text": [ "[9142, 9143, 9144, 9145]" ] } ], "prompt_number": 19 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that all three results come back at the same time, after all are finished computing.\n", "\n", "Let's now see what happens if we use non-blocking execution:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dview.block = False\n", "dview.apply(get_pid_slowly)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 20, "text": [ "" ] } ], "prompt_number": 20 }, { "cell_type": "markdown", "metadata": {}, "source": [ "What is returned is an ``AsyncResult`` object." ] }, { "cell_type": "code", "collapsed": false, "input": [ "res = dview.apply(get_pid_slowly)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 21 }, { "cell_type": "code", "collapsed": false, "input": [ "res.ready()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 22, "text": [ "False" ] } ], "prompt_number": 22 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can ask if the result is ready using the ``ready()`` command. Once it's ready, we can get the result with the ``get()`` command" ] }, { "cell_type": "code", "collapsed": false, "input": [ "res.ready()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 25, "text": [ "True" ] } ], "prompt_number": 25 }, { "cell_type": "code", "collapsed": false, "input": [ "res.get()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 26, "text": [ "[9142, 9143, 9144, 9145]" ] } ], "prompt_number": 26 }, { "cell_type": "markdown", "metadata": {}, "source": [ "For convenience, you can also use the ``apply_sync`` and ``apply_async`` commands" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dview.apply_sync(get_pid_slowly)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 27, "text": [ "[9142, 9143, 9144, 9145]" ] } ], "prompt_number": 27 }, { "cell_type": "code", "collapsed": false, "input": [ "dview.apply_async(get_pid_slowly)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 28, "text": [ "" ] } ], "prompt_number": 28 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### DirectView: Remote Imports\n", "\n", "You might notice that you get errors if you've not imported certain modules on the engines. For example:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy\n", "def normalize_vector(v):\n", " return numpy.asarray(v) / numpy.linalg.norm(v)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 36 }, { "cell_type": "code", "collapsed": false, "input": [ "x = numpy.random.random(5)\n", "normalize_vector(x)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 37, "text": [ "array([ 0.23527065, 0.60162073, 0.56038515, 0.32331687, 0.40513565])" ] } ], "prompt_number": 37 }, { "cell_type": "code", "collapsed": false, "input": [ "dview.block = True\n", "dview.apply(normalize_vector, x)" ], "language": "python", "metadata": {}, "outputs": [ { "ename": "CompositeError", "evalue": "one or more exceptions from call to method: normalize_vector\n[0:apply]: NameError: global name 'numpy' is not defined\n[1:apply]: NameError: global name 'numpy' is not defined\n[2:apply]: NameError: global name 'numpy' is not defined\n[3:apply]: NameError: global name 'numpy' is not defined", "output_type": "pyerr", "traceback": [ "[0:apply]: ", "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mnormalize_vector\u001b[0;34m(v)\u001b[0m", "\u001b[0;31mNameError\u001b[0m: global name 'numpy' is not defined", "", "[1:apply]: ", "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mnormalize_vector\u001b[0;34m(v)\u001b[0m", "\u001b[0;31mNameError\u001b[0m: global name 'numpy' is not defined", "", "[2:apply]: ", "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mnormalize_vector\u001b[0;34m(v)\u001b[0m", "\u001b[0;31mNameError\u001b[0m: global name 'numpy' is not defined", "", "[3:apply]: ", "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mnormalize_vector\u001b[0;34m(v)\u001b[0m", "\u001b[0;31mNameError\u001b[0m: global name 'numpy' is not defined", "" ] } ], "prompt_number": 38 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Though we've imported ``numpy`` on our *local* engine, we haven't imported ``numpy`` on any of our other engines, so the code won't work.\n", "\n", "There are a few ways to execute imports on other engines. We can do this directly with the ``execute`` method:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dview.execute('import numpy')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 39, "text": [ "" ] } ], "prompt_number": 39 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, we can use the ``sync_imports`` context manager to make this happen:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "with dview.sync_imports():\n", " import numpy" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "importing numpy on engine(s)\n" ] } ], "prompt_number": 40 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or, we can use the ``px`` (parallel execute) magic function to execute the contents of the cell on every engine:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%px import numpy" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 41 }, { "cell_type": "markdown", "metadata": {}, "source": [ "After doing any of these, we're able to run our function and see the results:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dview.apply(normalize_vector, x)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 42, "text": [ "[array([ 0.23527065, 0.60162073, 0.56038515, 0.32331687, 0.40513565]),\n", " array([ 0.23527065, 0.60162073, 0.56038515, 0.32331687, 0.40513565]),\n", " array([ 0.23527065, 0.60162073, 0.56038515, 0.32331687, 0.40513565]),\n", " array([ 0.23527065, 0.60162073, 0.56038515, 0.32331687, 0.40513565])]" ] } ], "prompt_number": 42 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### DirectView: running scripts remotely\n", "\n", "We can use a direct view to run a given script on each client. For example, let's look at the following script:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%file myscript.py\n", "import numpy\n", "\n", "a = 5\n", "\n", "def square(x):\n", " return x * x" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Overwriting myscript.py\n" ] } ], "prompt_number": 43 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can run this script on each of our clients:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dview.run(\"myscript.py\")" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 44, "text": [ "" ] } ], "prompt_number": 44 }, { "cell_type": "markdown", "metadata": {}, "source": [ "To look at the data, let's use the dictionary interface:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print dview['a']" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[5, 5, 5, 5]\n" ] } ], "prompt_number": 45 }, { "cell_type": "code", "collapsed": false, "input": [ "print dview['square']" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[, , , ]\n" ] } ], "prompt_number": 46 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also use the dictionary interface to assign data:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dview['b'] = 4\n", "print dview['b']" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[4, 4, 4, 4]\n" ] } ], "prompt_number": 47 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now the variables ``a`` and ``b`` are defined globally on all our engines." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### DirectView: execute() method\n", "\n", "Code can also be executed directly on the engine by passing strings to the engines.\n", "First, let's look at the definitions of ``a`` and ``b`` on our engines:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print dview['a']\n", "print dview['b']" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[5, 5, 5, 5]\n", "[4, 4, 4, 4]\n" ] } ], "prompt_number": 48 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we'll use ``execute()`` to add ``a`` and ``b`` and save the result to ``c``:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dview.execute('c=a+b')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 49, "text": [ "" ] } ], "prompt_number": 49 }, { "cell_type": "code", "collapsed": false, "input": [ "dview['c']" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 50, "text": [ "[9, 9, 9, 9]" ] } ], "prompt_number": 50 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also execute code on any subset of the engines:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "clients[:2].execute('c=a*b')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 51, "text": [ "" ] } ], "prompt_number": 51 }, { "cell_type": "code", "collapsed": false, "input": [ "dview['c']" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 52, "text": [ "[20, 20, 9, 9]" ] } ], "prompt_number": 52 }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is the basic way to push and pull data to and from the client and engines." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Parallel Magics\n", "\n", "We saw this above, but one nice way to interface to the clients is through the ``%px`` magic functions. This works only within the IPython notebook, but is a nice shortcut for simple parallel execution. Basically, anything after the ``%px`` on a line is executed on every engine:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%px c = numpy.random.random(3)\n", "%px print c" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[stdout:0] [ 0.50721809 0.17834299 0.03162916]\n", "[stdout:1] [ 0.08939572 0.08664146 0.27040773]\n", "[stdout:2] [ 0.00414367 0.43595796 0.17353835]\n", "[stdout:3] [ 0.6570126 0.06122939 0.16020218]\n" ] } ], "prompt_number": 53 }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you want to execute multiple lines at once, you can use the ``%%px`` cell magic to do this:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%px\n", "c = numpy.random.random(5)\n", "c *= a\n", "print c" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[stdout:0] [ 0.15017173 4.73927557 0.47193208 3.18212826 0.18068899]\n", "[stdout:1] [ 3.76819739 1.02773891 0.2910802 2.24805272 3.1696827 ]\n", "[stdout:2] [ 3.29312298 3.98483227 1.36147721 3.74585018 0.16350398]\n", "[stdout:3] [ 3.0226832 1.80901736 4.92593167 3.89666551 4.50883695]\n" ] } ], "prompt_number": 54 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Again, we can access the variables directly using the dictionary interface:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dview['c']" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 55, "text": [ "[array([ 0.15017173, 4.73927557, 0.47193208, 3.18212826, 0.18068899]),\n", " array([ 3.76819739, 1.02773891, 0.2910802 , 2.24805272, 3.1696827 ]),\n", " array([ 3.29312298, 3.98483227, 1.36147721, 3.74585018, 0.16350398]),\n", " array([ 3.0226832 , 1.80901736, 4.92593167, 3.89666551, 4.50883695])]" ] } ], "prompt_number": 55 }, { "cell_type": "markdown", "metadata": {}, "source": [ "### DirectView: Scatter and Gather\n", "\n", "One very useful way to push and pull data is using the ``scatter()`` and ``gather()`` commands. This will take an array and partition it among the parallel instances:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dview.scatter('a', np.arange(24))\n", "dview['a']" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 56, "text": [ "[array([0, 1, 2, 3, 4, 5]),\n", " array([ 6, 7, 8, 9, 10, 11]),\n", " array([12, 13, 14, 15, 16, 17]),\n", " array([18, 19, 20, 21, 22, 23])]" ] } ], "prompt_number": 56 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the contents of ``a`` are partitioned and scattered among the instances. To bring them back, we can use ``gather()``:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = dview.gather('a')\n", "a" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 57, "text": [ "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,\n", " 17, 18, 19, 20, 21, 22, 23])" ] } ], "prompt_number": 57 }, { "cell_type": "markdown", "metadata": {}, "source": [ "So, for example, you might do an operation something like this:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = np.random.random(400)\n", "dview.scatter('x', x)\n", "dview.execute('y = numpy.sqrt(x)')\n", "y = dview.gather('y')\n", "\n", "print np.allclose(y, np.sqrt(x))" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "True\n" ] } ], "prompt_number": 58 }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is a somewhat trivial computation, but if you had a larger computation that could be done on partitions of the data, it would allow you to speed your calculation according to the number of cores available." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example: distributed matrix multiplication\n", "\n", "Let's write a simple distributed matrix multiplication function.\n", "\n", "First, let's look at how ``scatter`` works with matrices:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "A = np.random.random((8, 3))\n", "dview.scatter('A', A)\n", "print A\n", "print\n", "for chunk in dview['A']:\n", " print chunk" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[[ 0.38270801 0.93567854 0.00724878]\n", " [ 0.1043931 0.88228169 0.89202187]\n", " [ 0.41265125 0.37364223 0.18220115]\n", " [ 0.73935114 0.60215577 0.66854311]\n", " [ 0.52294005 0.52325057 0.58609731]\n", " [ 0.92111696 0.9419077 0.44157558]\n", " [ 0.35245913 0.9811961 0.47649591]\n", " [ 0.01952694 0.05868491 0.57032717]]\n", "\n", "[[ 0.38270801 0.93567854 0.00724878]\n", " [ 0.1043931 0.88228169 0.89202187]]\n", "[[ 0.41265125 0.37364223 0.18220115]\n", " [ 0.73935114 0.60215577 0.66854311]]\n", "[[ 0.52294005 0.52325057 0.58609731]\n", " [ 0.92111696 0.9419077 0.44157558]]\n", "[[ 0.35245913 0.9811961 0.47649591]\n", " [ 0.01952694 0.05868491 0.57032717]]\n" ] } ], "prompt_number": 59 }, { "cell_type": "markdown", "metadata": {}, "source": [ "So scattering a matrix breaks it up into blocks... we can perform a matrix multiplication on each of these blocks, and gather the individual results to get the final result!" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def parallel_dot(dview, A, B):\n", " dview.scatter('A', A)\n", " dview['B'] = B\n", " dview.execute('C = numpy.dot(A, B)')\n", " return dview.gather('C')\n", "\n", "A = np.random.random((10, 3))\n", "B = np.random.random((3, 5))\n", "\n", "np.allclose(parallel_dot(dview, A, B),\n", " np.dot(A, B))" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 60, "text": [ "True" ] } ], "prompt_number": 60 }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Working with Load-balanced Views\n", "\n", "Direct views are a nice low-level interface to the clients, but for most tasks it can be more helpful to use Load-balanced views.\n", "\n", "A load-balanced view is a fault-tolerant way to distribute tasks among the engines. While there is no direct access to individual engines, it provides a simple and powerful interface." ] }, { "cell_type": "code", "collapsed": false, "input": [ "lview = clients.load_balanced_view()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 61 }, { "cell_type": "code", "collapsed": false, "input": [ "def sleep_and_return(factor=10):\n", " import time\n", " import random\n", " r = factor * random.random()\n", " time.sleep(r)\n", " return r" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 62 }, { "cell_type": "code", "collapsed": false, "input": [ "lview.block = True\n", "lview.apply(sleep_and_return, 1)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 63, "text": [ "0.383964253758315" ] } ], "prompt_number": 63 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using ``apply`` on a load balanced view simply executes the function once.\n", "\n", "We can use the ``map`` function to execute multiple inputs. We'll use ``block=False`` to make sure the results come asynchronously:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "lview.block = False\n", "res = lview.map(sleep_and_return, range(10))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 67 }, { "cell_type": "code", "collapsed": false, "input": [ "res.ready()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 68, "text": [ "False" ] } ], "prompt_number": 68 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ``progress`` attribute tells us how many of the jobs have been completed up to this point:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import time\n", "while not res.ready():\n", " time.sleep(1)\n", " print res.progress" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "6\n", "7" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "7" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "7" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "8" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "10" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n" ] } ], "prompt_number": 69 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once all the results are finished, we can use the ``result`` attribute to get at them:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "res.result" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 70, "text": [ "[0.0,\n", " 0.27259788387004413,\n", " 1.6492597432569556,\n", " 0.16940516700627017,\n", " 2.423163349769624,\n", " 1.3291874648520896,\n", " 0.676810918286002,\n", " 5.4501484144834675,\n", " 4.003957788350984,\n", " 4.828199829606783]" ] } ], "prompt_number": 70 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The load-balanced view also includes an iterator which will return results as they come in:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "for result in lview.map(sleep_and_return, range(10)):\n", " print result" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "0.0\n", "0.45237777481" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "1.09647522681" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "1.61237816742" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "2.05581658346" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "4.25450122799" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "0.0663860312067\n", "5.71882736737" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n", "2.49521158545\n", "7.23768335018" ] }, { "output_type": "stream", "stream": "stdout", "text": [ "\n" ] } ], "prompt_number": 71 }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercise: Monte Carlo $\\pi$\n", "\n", "Here you'll do a quick exercise where you estimate $\\pi$ using a rudimentary Monte Carlo method. Imagine you have a 2x2 square dart board and you randomly throw darts at it." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%pylab inline\n", "x, y = 2 * np.random.random((2, 500)) - 1\n", "\n", "ax = plt.axes(aspect='equal', xticks=[], yticks=[], frameon=False)\n", "ax.scatter(x, y, c=(x ** 2 + y ** 2 < 1), cmap=plt.cm.binary)\n", "ax.add_patch(mpl.patches.Circle((0, 0), 1, zorder=0, fc='#FFAAAA'))" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Populating the interactive namespace from numpy and matplotlib\n" ] }, { "metadata": {}, "output_type": "pyout", "prompt_number": 72, "text": [ "" ] }, { "metadata": {}, "output_type": "display_data", "png": "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\nVlZWBAYGFuh4GVGko3nh4eHY2tpqq3NNmzYlLCyMcePG8e7dO6ysrBAKhXTr1g0LCwtevnxJ27Zt\nUavVvHr1qkga1mKxGCMjI236kr5nzg1ly5Zl5+7d/Dl7NksWLiQiUwBKRCLK5lBMOpON+1vjHApB\nT9+/Z1cGsjqAubExByZMyPV6+zRvzuW5cznk6oqBRMLs3r2pX6kSpUxN2ZQmlDe/Tx8tNfN7Y2TH\njmx0dORrfDzKNIPrdUOH6rymcpkyen6+KUolpU1NmfP33xx2c2PipEn4njmDubk5KSkpbNu2jT59\n+tC6dWuOHz/OwoULtT3Xc+fOMWDAAIyMjIiKiqJhw4ZUq1YNszRzths3bmR7vY0bN6Z58+b88MMP\ndOvWjYsXL/L7779TtmzZAt1/lSpVeP/+PX5+ftSoUYO3b98SEhKSZ4JRTijSQtSTJ0/o27cvt27d\nombNmsyfP5+3b99qn35yuRylUomJiQmXL19m/Pjx9OnTBy8vL4yNjbl69apWD7mgePHiBd27d2fZ\nsmWYm5uzaNEi1q5dy7Bhw/J1nL/++ouxY8agUquRisWUNTPj5caN2VY6y0+cSGh0tM7vfmrShCvz\n52d7jjUXLrDszBmd4QQTAwO+HTuWr2v9X0VYTAy7rl0jKj6evi1a0D2L8cZ/PTwYtHUrQqGQFKWS\nX1u0wPntWwYMGMDSFSu0UkXpkMvlHDhwgJCQEFq1akXfvn11/p6UlMSnT58oV64cJUqUwM/Pj8TE\nROrUqaNXkMwMlUrFsWPHeP/+PY0aNWLgwIGFKpAePnyYuXPnUqtWLby9vdm5cydDMz24CoIirx7/\n9ddfzJgxg4SEBNq3b8+pU6eynZp4+/Yt9+7do3Tp0vTp06fQAZuOp0+fsmPHDpKTkxkyZAj9Czh5\n4uvry65du7jq6IihQMD6wYPpZWub5cpdcvRoHdaQAFg2cGCOk0F7btzA7vhxHYqglYUFoTmk84WB\ny5s3vP30iZrW1vRo1Og/syzJjC+xsamGV25udOjYkVXr1mm56l+/fmXOnDm8ffuWWrVqsXHjxv/5\nKZyMCA4OJiAggOrVq+s9gAqKYuvTKpXKIgvC/xoajYbLly+zfPFiEuPimNylC7937KgzMD5+3z7+\nvn8/X6T6eLkc27lzCfn6NdVNXiwukCFVXrDg77/Zef06SrUasVDIqI4d2T1uXIGO9T4sjJG7duH3\n+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\nRoRWELzMn4oP5P53e9NtAAAAAElFTkSuQmCC\n", "text": [ "" ] } ], "prompt_number": 72 }, { "cell_type": "markdown", "metadata": {}, "source": [ " The probability that those darts will fall within 1 unit of the center is\n", "\n", "$$\n", "p = \\frac{\\rm Area~of~circle}{Area~of~square} = \\frac{\\pi\\cdot 1^2}{2^2} = \\frac{\\pi}{4}\n", "$$\n", "\n", "So if you throw $N$ darts, you can estimate $\\pi$ to be equal to\n", "$$\n", "\\pi = 4\\frac{N_{in}}{N}\n", "$$\n", "\n", "Here we'll write a function to estimate $\\pi$ using a random number generator:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def estimate_pi(N):\n", " r = np.random.random((N, 2))\n", " inside = np.sum(r ** 2, 1) <= 1\n", " return 4 * inside.sum() * 1. / N" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 73 }, { "cell_type": "code", "collapsed": false, "input": [ "estimate_pi(1E6)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 74, "text": [ "3.1420720000000002" ] } ], "prompt_number": 74 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Write a function which uses a **Load-balanced View** to parallelize this estimation of pi:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def estimate_pi(N, lview, N_per_trial=1E6):\n", " # your code here:\n", " # distribute the N trials across the load-balanced view,\n", " # using lview.map() and return the average of the results" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that this is certainly **not** the best way to estimate $\\pi$, but it shows how you can use IPython parallel to do distributed Monte Carlo simulations, which can be **very** useful in practice." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Homework\n", "\n", "For the homework today, we'll look at two Astronomy applications. You may **choose one** (or both, if you want more practice) to turn in. In both of them, we'll return to a problem that we've seen before, but extend our computation using IPython parallel.\n", "\n", "As usual, you can turn-in your results via GitHub: use either an IPython notebook, or a stand-alone ``.py`` file." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. Cross-validation of photometric redshifts\n", "\n", "In the [Scikit-learn homework](http://www.astro.washington.edu/users/vanderplas/Astr599/notebooks/17_SklearnIntro) a few weeks ago, we looked at different regression schemes for computing photometric redshifts (see Exercise 2). Return to this, and determine the minimum rms you can achieve given combinations of ``max_depth`` and ``n_estimators`` in the random forest regressor\n", "\n", "Here's how we'll download and prepare the data:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from astroML.datasets import fetch_sdss_specgals\n", "import numpy as np\n", "data = fetch_sdss_specgals()\n", "\n", "# put magnitudes in a matrix\n", "X = np.vstack([data['modelMag_%s' % f] for f in 'ugriz']).T\n", "y = data['z']\n", "\n", "# down-sample the data for speed\n", "X = X[::10]\n", "y = y[::10]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here's an example of using cross-validation to compute the ``r2`` score for a given ``C``:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from sklearn.ensemble import RandomForestRegressor\n", "from sklearn.cross_validation import cross_val_score, StratifiedKFold\n", "\n", "# define the model with the given value of C\n", "model = RandomForestRegressor(n_estimators=10, max_depth=3)\n", "\n", "# compute the scores via cross-validation\n", "scores = cross_val_score(model, X, y,\n", " scoring='r2', cv=3)\n", "\n", "# print the mean of the cross-validation scores\n", "score = np.mean(scores)\n", "print score" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Write a script that uses a parallel computation to explore what the best value of ``max_depth`` and ``n_estimators`` is. What's the maximal score you can obtain?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Computing Periods of Stars\n", "\n", "In the lecture on [optimization](http://www.astro.washington.edu/users/vanderplas/Astr599/notebooks/14_optimization), we looked at computing the periods of LINEAR stars using the lomb-scargle algorithm.\n", "\n", "Write a script which uses IPython parallel to compute the periods of ~1000 stars from the LINEAR dataset. Plot the log of the period you found vs the g-i color of the star. You can compare your results to [this paper](http://adsabs.harvard.edu/abs/2013AJ....146..101P), though the Lomb-Scargle period-finder might lead to slightly different results.\n", "\n", "Here's how to get the data:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from astroML.datasets import fetch_LINEAR_sample\n", "lcs = fetch_LINEAR_sample()\n", "\n", "id_ = lcs.ids[0]\n", "time, flux, dflux = lcs[id_].T" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And here's how to compute the lomb-scargle periodogram:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from astroML.time_series import lomb_scargle\n", "periods = np.logspace(-2, 0, 10000)\n", "periodogram = lomb_scargle(time, flux, dflux, omega=2 * np.pi / periods, generalized=True)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we find the maximum period:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "idx = np.argsort(periodogram)\n", "print periods[idx[-1]]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And we get the $g-r$ color:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "g_r = lcs.get_target_parameter(id_, 'gr')\n", "print g_r" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You'll have to automate the task of computing the best period, and use a ``LoadBalancedView`` to distribute this across as many cores as you have available." ] } ], "metadata": {} } ] }