{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Using Parallel Magics" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "IPython has a few magics for working with your engines.\n", "\n", "This assumes you have started an IPython cluster, either with the notebook interface,\n", "or the `ipcluster/controller/engine` commands." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from IPython import parallel\n", "rc = parallel.Client()\n", "dv = rc[:]\n", "rc.ids" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Creating a Client registers the parallel magics `%px`, `%%px`, `%pxresult`, `pxconfig`, and `%autopx`. \n", "These magics are initially associated with a DirectView always associated with all currently registered engines." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can execute code remotely with `%px`:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%px a=5" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%px print(a)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%px a" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "with dv.sync_imports():\n", " import sys" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%px from __future__ import print_function\n", "%px print(\"ERROR\", file=sys.stderr)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You don't have to wait for results. The `%pxconfig` magic lets you change the default blocking/targets for the `%px` magics:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%pxconfig --noblock" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%px import time\n", "%px time.sleep(5)\n", "%px time.time()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But you will notice that this didn't output the result of the last command.\n", "For this, we have `%pxresult`, which displays the output of the latest request:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%pxresult" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remember, an IPython engine is IPython, so you can do magics remotely as well!" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%pxconfig --block\n", "%px %matplotlib inline" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%%px\n", "import numpy as np\n", "import matplotlib.pyplot as plt" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`%%px` can also be used as a cell magic, for submitting whole blocks.\n", "This one acceps `--block` and `--noblock` flags to specify\n", "the blocking behavior, though the default is unchanged.\n" ] }, { "cell_type": "code", "collapsed": false, "input": [ "dv.scatter('id', dv.targets, flatten=True)\n", "dv['stride'] = len(dv)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%%px --noblock\n", "x = np.linspace(0,np.pi,1000)\n", "for n in range(id,12, stride):\n", " print(n)\n", " plt.plot(x,np.sin(n*x))\n", "plt.title(\"Plot %i\" % id)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%pxresult" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It also lets you choose some amount of the grouping of the outputs with `--group-outputs`:\n", "\n", "The choices are:\n", "\n", "* `engine` - all of an engine's output is collected together\n", "* `type` - where stdout of each engine is grouped, etc. (the default)\n", "* `order` - same as `type`, but individual displaypub outputs are interleaved.\n", " That is, it will output the first plot from each engine, then the second from each,\n", " etc." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%px --group-outputs=engine\n", "x = np.linspace(0,np.pi,1000)\n", "for n in range(id+1,12, stride):\n", " print(n)\n", " plt.figure()\n", " plt.plot(x,np.sin(n*x))\n", " plt.title(\"Plot %i\" % n)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When you specify 'order', then individual display outputs (e.g. plots) will be interleaved.\n", "\n", "`%pxresult` takes the same output-ordering arguments as `%%px`, \n", "so you can view the previous result in a variety of different ways with a few sequential calls to `%pxresult`:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%pxresult --group-outputs=order" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Single-engine views" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When a DirectView has a single target, the output is a bit simpler (no prefixes on stdout/err, etc.):" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from __future__ import print_function\n", "\n", "def generate_output():\n", " \"\"\"function for testing output\n", " \n", " publishes two outputs of each type, and returns something\n", " \"\"\"\n", " \n", " import sys,os\n", " from IPython.display import display, HTML, Math\n", " \n", " print(\"stdout\")\n", " print(\"stderr\", file=sys.stderr)\n", " \n", " display(HTML(\"HTML\"))\n", " \n", " print(\"stdout2\")\n", " print(\"stderr2\", file=sys.stderr)\n", " \n", " display(Math(r\"\\alpha=\\beta\"))\n", " \n", " return os.getpid()\n", "\n", "dv['generate_output'] = generate_output" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also have more than one set of parallel magics registered at a time.\n", "\n", "The `View.activate()` method takes a suffix argument, which is added to `'px'`." ] }, { "cell_type": "code", "collapsed": false, "input": [ "e0 = rc[-1]\n", "e0.block = True\n", "e0.activate('0')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%px0 generate_output()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%px generate_output()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As mentioned above, we can redisplay those same results with various grouping:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%pxresult --group-outputs order" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "%pxresult --group-outputs engine" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Parallel Exceptions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When you raise exceptions with the parallel exception,\n", "the CompositeError raised locally will display your remote traceback." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%px\n", "from numpy.random import random\n", "A = random((100,100,'invalid shape'))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Remote Cell Magics" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remember, Engines are IPython too, so the cell that is run remotely by %%px can in turn use a cell magic." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%px\n", "%%timeit\n", "from numpy.random import random\n", "from numpy.linalg import norm\n", "A = random((100,100))\n", "norm(A, 2)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Local Execution" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As of IPython 1.0, you can instruct `%%px` to also execute the cell locally.\n", "This is useful for interactive definitions,\n", "or if you want to load a data source everywhere,\n", "not just on the engines." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%px --local\n", "import os\n", "thispid = os.getpid()\n", "print(thispid)" ], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }