##// END OF EJS Templates
Updating a few example notebooks to v3.
Brian Granger -
Show More
@@ -1,193 +1,381 b''
1 1 {
2 "metadata": {
3 "name": "BackgroundJobs"
4 },
5 "nbformat": 3,
6 "nbformat_minor": 0,
2 7 "worksheets": [
3 8 {
4 9 "cells": [
5 10 {
6 "source": "# Simple interactive bacgkround jobs with IPython\n\nWe start by loading the `backgroundjobs` library and defining a few trivial functions to illustrate things with.",
7 "cell_type": "markdown"
11 "cell_type": "markdown",
12 "metadata": {},
13 "source": [
14 "# Simple interactive bacgkround jobs with IPython\n",
15 "\n",
16 "We start by loading the `backgroundjobs` library and defining a few trivial functions to illustrate things with."
17 ]
8 18 },
9 19 {
10 20 "cell_type": "code",
21 "collapsed": false,
22 "input": [
23 "from IPython.lib import backgroundjobs as bg\n",
24 "\n",
25 "import sys\n",
26 "import time\n",
27 "\n",
28 "def sleepfunc(interval=2, *a, **kw):\n",
29 " args = dict(interval=interval,\n",
30 " args=a,\n",
31 " kwargs=kw)\n",
32 " time.sleep(interval)\n",
33 " return args\n",
34 "\n",
35 "def diefunc(interval=2, *a, **kw):\n",
36 " time.sleep(interval)\n",
37 " raise Exception(\"Dead job with interval %s\" % interval)\n",
38 "\n",
39 "def printfunc(interval=1, reps=5):\n",
40 " for n in range(reps):\n",
41 " time.sleep(interval)\n",
42 " print 'In the background...', n\n",
43 " sys.stdout.flush()\n",
44 " print 'All done!'\n",
45 " sys.stdout.flush()"
46 ],
11 47 "language": "python",
48 "metadata": {},
12 49 "outputs": [],
13 "collapsed": false,
14 "prompt_number": 35,
15 "input": "from IPython.lib import backgroundjobs as bg\n\nimport sys\nimport time\n\ndef sleepfunc(interval=2, *a, **kw):\n args = dict(interval=interval,\n args=a,\n kwargs=kw)\n time.sleep(interval)\n return args\n\ndef diefunc(interval=2, *a, **kw):\n time.sleep(interval)\n raise Exception(\"Dead job with interval %s\" % interval)\n\ndef printfunc(interval=1, reps=5):\n for n in range(reps):\n time.sleep(interval)\n print 'In the background...', n\n sys.stdout.flush()\n print 'All done!'\n sys.stdout.flush()"
50 "prompt_number": 35
16 51 },
17 52 {
18 "source": "Now, we can create a job manager (called simply `jobs`) and use it to submit new jobs.\n<br>\nRun the cell below and wait a few seconds for the whole thing to finish, until you see the \"All done!\" printout.",
19 "cell_type": "markdown"
53 "cell_type": "markdown",
54 "metadata": {},
55 "source": [
56 "Now, we can create a job manager (called simply `jobs`) and use it to submit new jobs.\n",
57 "<br>\n",
58 "Run the cell below and wait a few seconds for the whole thing to finish, until you see the \"All done!\" printout."
59 ]
20 60 },
21 61 {
22 62 "cell_type": "code",
63 "collapsed": false,
64 "input": [
65 "jobs = bg.BackgroundJobManager()\n",
66 "\n",
67 "# Start a few jobs, the first one will have ID # 0\n",
68 "jobs.new(sleepfunc, 4)\n",
69 "jobs.new(sleepfunc, kw={'reps':2})\n",
70 "jobs.new('printfunc(1,3)')\n",
71 "\n",
72 "# This makes a couple of jobs which will die. Let's keep a reference to\n",
73 "# them for easier traceback reporting later\n",
74 "diejob1 = jobs.new(diefunc, 1)\n",
75 "diejob2 = jobs.new(diefunc, 2)"
76 ],
23 77 "language": "python",
78 "metadata": {},
24 79 "outputs": [
25 80 {
26 81 "output_type": "stream",
27 82 "stream": "stdout",
28 "text": "Starting job # 0 in a separate thread.\nStarting job # 2 in a separate thread.\nStarting job # 3 in a separate thread.\nStarting job # 4 in a separate thread.\nStarting job # 5 in a separate thread.\n"
83 "text": [
84 "Starting job # 0 in a separate thread.\n",
85 "Starting job # 2 in a separate thread.\n",
86 "Starting job # 3 in a separate thread.\n",
87 "Starting job # 4 in a separate thread.\n",
88 "Starting job # 5 in a separate thread.\n"
89 ]
29 90 },
30 91 {
31 92 "output_type": "stream",
32 93 "stream": "stdout",
33 "text": "In the background... 0\n"
94 "text": [
95 "In the background... 0\n"
96 ]
34 97 },
35 98 {
36 99 "output_type": "stream",
37 100 "stream": "stdout",
38 "text": "In the background... 1\n"
101 "text": [
102 "In the background... 1\n"
103 ]
39 104 },
40 105 {
41 106 "output_type": "stream",
42 107 "stream": "stdout",
43 "text": "In the background... 2\n"
108 "text": [
109 "In the background... 2\n"
110 ]
44 111 },
45 112 {
46 113 "output_type": "stream",
47 114 "stream": "stdout",
48 "text": "All done!\n"
115 "text": [
116 "All done!\n"
117 ]
49 118 }
50 119 ],
51 "collapsed": false,
52 "prompt_number": 36,
53 "input": "jobs = bg.BackgroundJobManager()\n\n# Start a few jobs, the first one will have ID # 0\njobs.new(sleepfunc, 4)\njobs.new(sleepfunc, kw={'reps':2})\njobs.new('printfunc(1,3)')\n\n# This makes a couple of jobs which will die. Let's keep a reference to\n# them for easier traceback reporting later\ndiejob1 = jobs.new(diefunc, 1)\ndiejob2 = jobs.new(diefunc, 2)"
120 "prompt_number": 36
54 121 },
55 122 {
56 "source": "You can check the status of your jobs at any time:",
57 "cell_type": "markdown"
123 "cell_type": "markdown",
124 "metadata": {},
125 "source": [
126 "You can check the status of your jobs at any time:"
127 ]
58 128 },
59 129 {
60 130 "cell_type": "code",
131 "collapsed": false,
132 "input": [
133 "jobs.status()"
134 ],
61 135 "language": "python",
136 "metadata": {},
62 137 "outputs": [
63 138 {
64 139 "output_type": "stream",
65 140 "stream": "stdout",
66 "text": "Completed jobs:\n0 : &lt;function sleepfunc at 0x30e1578&gt;\n2 : &lt;function sleepfunc at 0x30e1578&gt;\n3 : printfunc(1,3)\n\nDead jobs:\n4 : &lt;function diefunc at 0x304d488&gt;\n5 : &lt;function diefunc at 0x304d488&gt;\n\n"
141 "text": [
142 "Completed jobs:\n",
143 "0 : &lt;function sleepfunc at 0x30e1578&gt;\n",
144 "2 : &lt;function sleepfunc at 0x30e1578&gt;\n",
145 "3 : printfunc(1,3)\n",
146 "\n",
147 "Dead jobs:\n",
148 "4 : &lt;function diefunc at 0x304d488&gt;\n",
149 "5 : &lt;function diefunc at 0x304d488&gt;\n",
150 "\n"
151 ]
67 152 }
68 153 ],
69 "collapsed": false,
70 "prompt_number": 37,
71 "input": "jobs.status()"
154 "prompt_number": 37
72 155 },
73 156 {
74 "source": "For any completed job, you can get its result easily:",
75 "cell_type": "markdown"
157 "cell_type": "markdown",
158 "metadata": {},
159 "source": [
160 "For any completed job, you can get its result easily:"
161 ]
76 162 },
77 163 {
78 164 "cell_type": "code",
165 "collapsed": false,
166 "input": [
167 "jobs[0].result\n",
168 "j0 = jobs[0]\n",
169 "j0.join?"
170 ],
79 171 "language": "python",
172 "metadata": {},
80 173 "outputs": [],
81 "collapsed": false,
82 "prompt_number": 43,
83 "input": "jobs[0].result\nj0 = jobs[0]\nj0.join?"
174 "prompt_number": 43
84 175 },
85 176 {
86 "source": "You can get the traceback of any dead job. Run the line\nbelow again interactively until it prints a traceback (check the status\nof the job):\n",
87 "cell_type": "markdown"
177 "cell_type": "markdown",
178 "metadata": {},
179 "source": [
180 "You can get the traceback of any dead job. Run the line\n",
181 "below again interactively until it prints a traceback (check the status\n",
182 "of the job):\n"
183 ]
88 184 },
89 185 {
90 186 "cell_type": "code",
187 "collapsed": false,
188 "input": [
189 "print \"Status of diejob1:\", diejob1.status\n",
190 "diejob1.traceback() # jobs.traceback(4) would also work here, with the job number"
191 ],
91 192 "language": "python",
193 "metadata": {},
92 194 "outputs": [
93 195 {
94 196 "output_type": "stream",
95 197 "stream": "stdout",
96 "text": "Status of diejob1: Dead (Exception), call jobs.traceback() for details\n<span class=\"ansired\">---------------------------------------------------------------------------</span>\n<span class=\"ansired\">Exception</span> Traceback (most recent call last)\n<span class=\"ansigreen\">/home/fperez/usr/lib/python2.6/site-packages/IPython/lib/backgroundjobs.py</span> in <span class=\"ansicyan\">call</span><span class=\"ansiblue\">(self)</span>\n<span class=\"ansigreen\"> 462</span> <span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 463</span> <span class=\"ansigreen\">def</span> call<span class=\"ansiyellow\">(</span>self<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\">--&gt; 464</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">return</span> self<span class=\"ansiyellow\">.</span>func<span class=\"ansiyellow\">(</span><span class=\"ansiyellow\">*</span>self<span class=\"ansiyellow\">.</span>args<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>self<span class=\"ansiyellow\">.</span>kwargs<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n\n<span class=\"ansigreen\">/home/fperez/ipython/ipython/docs/examples/lib/&lt;ipython-input-15-54795a097787&gt;</span> in <span class=\"ansicyan\">diefunc</span><span class=\"ansiblue\">(interval, *a, **kw)</span>\n<span class=\"ansigreen\"> 14</span> <span class=\"ansigreen\">def</span> diefunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">2</span><span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">*</span>a<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>kw<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 15</span> time<span class=\"ansiyellow\">.</span>sleep<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\">---&gt; 16</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">raise</span> Exception<span class=\"ansiyellow\">(</span><span class=\"ansiblue\">&quot;Dead job with interval %s&quot;</span> <span class=\"ansiyellow\">%</span> interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 17</span> <span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 18</span> <span class=\"ansigreen\">def</span> printfunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">1</span><span class=\"ansiyellow\">,</span> reps<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">5</span><span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n\n<span class=\"ansired\">Exception</span>: Dead job with interval 1\n"
198 "text": [
199 "Status of diejob1: Dead (Exception), call jobs.traceback() for details\n",
200 "<span class=\"ansired\">---------------------------------------------------------------------------</span>\n",
201 "<span class=\"ansired\">Exception</span> Traceback (most recent call last)\n",
202 "<span class=\"ansigreen\">/home/fperez/usr/lib/python2.6/site-packages/IPython/lib/backgroundjobs.py</span> in <span class=\"ansicyan\">call</span><span class=\"ansiblue\">(self)</span>\n",
203 "<span class=\"ansigreen\"> 462</span> <span class=\"ansiyellow\"></span>\n",
204 "<span class=\"ansigreen\"> 463</span> <span class=\"ansigreen\">def</span> call<span class=\"ansiyellow\">(</span>self<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n",
205 "<span class=\"ansigreen\">--&gt; 464</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">return</span> self<span class=\"ansiyellow\">.</span>func<span class=\"ansiyellow\">(</span><span class=\"ansiyellow\">*</span>self<span class=\"ansiyellow\">.</span>args<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>self<span class=\"ansiyellow\">.</span>kwargs<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
206 "\n",
207 "<span class=\"ansigreen\">/home/fperez/ipython/ipython/docs/examples/lib/&lt;ipython-input-15-54795a097787&gt;</span> in <span class=\"ansicyan\">diefunc</span><span class=\"ansiblue\">(interval, *a, **kw)</span>\n",
208 "<span class=\"ansigreen\"> 14</span> <span class=\"ansigreen\">def</span> diefunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">2</span><span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">*</span>a<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>kw<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n",
209 "<span class=\"ansigreen\"> 15</span> time<span class=\"ansiyellow\">.</span>sleep<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
210 "<span class=\"ansigreen\">---&gt; 16</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">raise</span> Exception<span class=\"ansiyellow\">(</span><span class=\"ansiblue\">&quot;Dead job with interval %s&quot;</span> <span class=\"ansiyellow\">%</span> interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
211 "<span class=\"ansigreen\"> 17</span> <span class=\"ansiyellow\"></span>\n",
212 "<span class=\"ansigreen\"> 18</span> <span class=\"ansigreen\">def</span> printfunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">1</span><span class=\"ansiyellow\">,</span> reps<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">5</span><span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n",
213 "\n",
214 "<span class=\"ansired\">Exception</span>: Dead job with interval 1\n"
215 ]
97 216 }
98 217 ],
99 "collapsed": false,
100 "prompt_number": 34,
101 "input": "print \"Status of diejob1:\", diejob1.status\ndiejob1.traceback() # jobs.traceback(4) would also work here, with the job number"
218 "prompt_number": 34
102 219 },
103 220 {
104 "source": "This will print all tracebacks for all dead jobs:",
105 "cell_type": "markdown"
221 "cell_type": "markdown",
222 "metadata": {},
223 "source": [
224 "This will print all tracebacks for all dead jobs:"
225 ]
106 226 },
107 227 {
108 228 "cell_type": "code",
229 "collapsed": false,
230 "input": [
231 "jobs.traceback()"
232 ],
109 233 "language": "python",
234 "metadata": {},
110 235 "outputs": [
111 236 {
112 237 "output_type": "stream",
113 238 "stream": "stdout",
114 "text": "Traceback for: &lt;BackgroundJob #4: &lt;function diefunc at 0x30df758&gt;&gt;\n<span class=\"ansired\">---------------------------------------------------------------------------</span>\n<span class=\"ansired\">Exception</span> Traceback (most recent call last)\n<span class=\"ansigreen\">/home/fperez/usr/lib/python2.6/site-packages/IPython/lib/backgroundjobs.py</span> in <span class=\"ansicyan\">call</span><span class=\"ansiblue\">(self)</span>\n<span class=\"ansigreen\"> 462</span> <span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 463</span> <span class=\"ansigreen\">def</span> call<span class=\"ansiyellow\">(</span>self<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\">--&gt; 464</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">return</span> self<span class=\"ansiyellow\">.</span>func<span class=\"ansiyellow\">(</span><span class=\"ansiyellow\">*</span>self<span class=\"ansiyellow\">.</span>args<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>self<span class=\"ansiyellow\">.</span>kwargs<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n\n<span class=\"ansigreen\">/home/fperez/ipython/ipython/docs/examples/lib/&lt;ipython-input-15-54795a097787&gt;</span> in <span class=\"ansicyan\">diefunc</span><span class=\"ansiblue\">(interval, *a, **kw)</span>\n<span class=\"ansigreen\"> 14</span> <span class=\"ansigreen\">def</span> diefunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">2</span><span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">*</span>a<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>kw<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 15</span> time<span class=\"ansiyellow\">.</span>sleep<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\">---&gt; 16</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">raise</span> Exception<span class=\"ansiyellow\">(</span><span class=\"ansiblue\">&quot;Dead job with interval %s&quot;</span> <span class=\"ansiyellow\">%</span> interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 17</span> <span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 18</span> <span class=\"ansigreen\">def</span> printfunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">1</span><span class=\"ansiyellow\">,</span> reps<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">5</span><span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n\n<span class=\"ansired\">Exception</span>: Dead job with interval 1\n\nTraceback for: &lt;BackgroundJob #5: &lt;function diefunc at 0x30df758&gt;&gt;\n<span class=\"ansired\">---------------------------------------------------------------------------</span>\n<span class=\"ansired\">Exception</span> Traceback (most recent call last)\n<span class=\"ansigreen\">/home/fperez/usr/lib/python2.6/site-packages/IPython/lib/backgroundjobs.py</span> in <span class=\"ansicyan\">call</span><span class=\"ansiblue\">(self)</span>\n<span class=\"ansigreen\"> 462</span> <span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 463</span> <span class=\"ansigreen\">def</span> call<span class=\"ansiyellow\">(</span>self<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\">--&gt; 464</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">return</span> self<span class=\"ansiyellow\">.</span>func<span class=\"ansiyellow\">(</span><span class=\"ansiyellow\">*</span>self<span class=\"ansiyellow\">.</span>args<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>self<span class=\"ansiyellow\">.</span>kwargs<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n\n<span class=\"ansigreen\">/home/fperez/ipython/ipython/docs/examples/lib/&lt;ipython-input-15-54795a097787&gt;</span> in <span class=\"ansicyan\">diefunc</span><span class=\"ansiblue\">(interval, *a, **kw)</span>\n<span class=\"ansigreen\"> 14</span> <span class=\"ansigreen\">def</span> diefunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">2</span><span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">*</span>a<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>kw<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 15</span> time<span class=\"ansiyellow\">.</span>sleep<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\">---&gt; 16</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">raise</span> Exception<span class=\"ansiyellow\">(</span><span class=\"ansiblue\">&quot;Dead job with interval %s&quot;</span> <span class=\"ansiyellow\">%</span> interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 17</span> <span class=\"ansiyellow\"></span>\n<span class=\"ansigreen\"> 18</span> <span class=\"ansigreen\">def</span> printfunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">1</span><span class=\"ansiyellow\">,</span> reps<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">5</span><span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n\n<span class=\"ansired\">Exception</span>: Dead job with interval 2\n\n"
239 "text": [
240 "Traceback for: &lt;BackgroundJob #4: &lt;function diefunc at 0x30df758&gt;&gt;\n",
241 "<span class=\"ansired\">---------------------------------------------------------------------------</span>\n",
242 "<span class=\"ansired\">Exception</span> Traceback (most recent call last)\n",
243 "<span class=\"ansigreen\">/home/fperez/usr/lib/python2.6/site-packages/IPython/lib/backgroundjobs.py</span> in <span class=\"ansicyan\">call</span><span class=\"ansiblue\">(self)</span>\n",
244 "<span class=\"ansigreen\"> 462</span> <span class=\"ansiyellow\"></span>\n",
245 "<span class=\"ansigreen\"> 463</span> <span class=\"ansigreen\">def</span> call<span class=\"ansiyellow\">(</span>self<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n",
246 "<span class=\"ansigreen\">--&gt; 464</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">return</span> self<span class=\"ansiyellow\">.</span>func<span class=\"ansiyellow\">(</span><span class=\"ansiyellow\">*</span>self<span class=\"ansiyellow\">.</span>args<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>self<span class=\"ansiyellow\">.</span>kwargs<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
247 "\n",
248 "<span class=\"ansigreen\">/home/fperez/ipython/ipython/docs/examples/lib/&lt;ipython-input-15-54795a097787&gt;</span> in <span class=\"ansicyan\">diefunc</span><span class=\"ansiblue\">(interval, *a, **kw)</span>\n",
249 "<span class=\"ansigreen\"> 14</span> <span class=\"ansigreen\">def</span> diefunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">2</span><span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">*</span>a<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>kw<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n",
250 "<span class=\"ansigreen\"> 15</span> time<span class=\"ansiyellow\">.</span>sleep<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
251 "<span class=\"ansigreen\">---&gt; 16</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">raise</span> Exception<span class=\"ansiyellow\">(</span><span class=\"ansiblue\">&quot;Dead job with interval %s&quot;</span> <span class=\"ansiyellow\">%</span> interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
252 "<span class=\"ansigreen\"> 17</span> <span class=\"ansiyellow\"></span>\n",
253 "<span class=\"ansigreen\"> 18</span> <span class=\"ansigreen\">def</span> printfunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">1</span><span class=\"ansiyellow\">,</span> reps<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">5</span><span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n",
254 "\n",
255 "<span class=\"ansired\">Exception</span>: Dead job with interval 1\n",
256 "\n",
257 "Traceback for: &lt;BackgroundJob #5: &lt;function diefunc at 0x30df758&gt;&gt;\n",
258 "<span class=\"ansired\">---------------------------------------------------------------------------</span>\n",
259 "<span class=\"ansired\">Exception</span> Traceback (most recent call last)\n",
260 "<span class=\"ansigreen\">/home/fperez/usr/lib/python2.6/site-packages/IPython/lib/backgroundjobs.py</span> in <span class=\"ansicyan\">call</span><span class=\"ansiblue\">(self)</span>\n",
261 "<span class=\"ansigreen\"> 462</span> <span class=\"ansiyellow\"></span>\n",
262 "<span class=\"ansigreen\"> 463</span> <span class=\"ansigreen\">def</span> call<span class=\"ansiyellow\">(</span>self<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n",
263 "<span class=\"ansigreen\">--&gt; 464</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">return</span> self<span class=\"ansiyellow\">.</span>func<span class=\"ansiyellow\">(</span><span class=\"ansiyellow\">*</span>self<span class=\"ansiyellow\">.</span>args<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>self<span class=\"ansiyellow\">.</span>kwargs<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
264 "\n",
265 "<span class=\"ansigreen\">/home/fperez/ipython/ipython/docs/examples/lib/&lt;ipython-input-15-54795a097787&gt;</span> in <span class=\"ansicyan\">diefunc</span><span class=\"ansiblue\">(interval, *a, **kw)</span>\n",
266 "<span class=\"ansigreen\"> 14</span> <span class=\"ansigreen\">def</span> diefunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">2</span><span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">*</span>a<span class=\"ansiyellow\">,</span> <span class=\"ansiyellow\">**</span>kw<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n",
267 "<span class=\"ansigreen\"> 15</span> time<span class=\"ansiyellow\">.</span>sleep<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
268 "<span class=\"ansigreen\">---&gt; 16</span><span class=\"ansiyellow\"> </span><span class=\"ansigreen\">raise</span> Exception<span class=\"ansiyellow\">(</span><span class=\"ansiblue\">&quot;Dead job with interval %s&quot;</span> <span class=\"ansiyellow\">%</span> interval<span class=\"ansiyellow\">)</span><span class=\"ansiyellow\"></span>\n",
269 "<span class=\"ansigreen\"> 17</span> <span class=\"ansiyellow\"></span>\n",
270 "<span class=\"ansigreen\"> 18</span> <span class=\"ansigreen\">def</span> printfunc<span class=\"ansiyellow\">(</span>interval<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">1</span><span class=\"ansiyellow\">,</span> reps<span class=\"ansiyellow\">=</span><span class=\"ansicyan\">5</span><span class=\"ansiyellow\">)</span><span class=\"ansiyellow\">:</span><span class=\"ansiyellow\"></span>\n",
271 "\n",
272 "<span class=\"ansired\">Exception</span>: Dead job with interval 2\n",
273 "\n"
274 ]
115 275 }
116 276 ],
117 "collapsed": false,
118 "prompt_number": 33,
119 "input": "jobs.traceback()"
277 "prompt_number": 33
120 278 },
121 279 {
122 "source": "The job manager can be flushed of all completed jobs at any time:",
123 "cell_type": "markdown"
280 "cell_type": "markdown",
281 "metadata": {},
282 "source": [
283 "The job manager can be flushed of all completed jobs at any time:"
284 ]
124 285 },
125 286 {
126 287 "cell_type": "code",
288 "collapsed": false,
289 "input": [
290 "jobs.flush()"
291 ],
127 292 "language": "python",
293 "metadata": {},
128 294 "outputs": [
129 295 {
130 296 "output_type": "stream",
131 297 "stream": "stdout",
132 "text": "No jobs to flush.\n"
298 "text": [
299 "No jobs to flush.\n"
300 ]
133 301 }
134 302 ],
135 "collapsed": false,
136 "prompt_number": 25,
137 "input": "jobs.flush()"
303 "prompt_number": 25
138 304 },
139 305 {
140 "source": "After that, the status is simply empty:",
141 "cell_type": "markdown"
306 "cell_type": "markdown",
307 "metadata": {},
308 "source": [
309 "After that, the status is simply empty:"
310 ]
142 311 },
143 312 {
144 313 "cell_type": "code",
314 "collapsed": true,
315 "input": [
316 "jobs.status()"
317 ],
145 318 "language": "python",
319 "metadata": {},
146 320 "outputs": [],
147 "collapsed": true,
148 "prompt_number": 27,
149 "input": "jobs.status()"
321 "prompt_number": 27
150 322 },
151 323 {
152 "source": "It's easy to wait on a job:",
153 "cell_type": "markdown"
324 "cell_type": "markdown",
325 "metadata": {},
326 "source": [
327 "It's easy to wait on a job:"
328 ]
154 329 },
155 330 {
156 331 "cell_type": "code",
332 "collapsed": false,
333 "input": [
334 "j = jobs.new(sleepfunc, 2)\n",
335 "print \"Will wait for j now...\"\n",
336 "sys.stdout.flush()\n",
337 "j.join()\n",
338 "print \"Result from j:\"\n",
339 "j.result"
340 ],
157 341 "language": "python",
342 "metadata": {},
158 343 "outputs": [
159 344 {
160 345 "output_type": "stream",
161 346 "stream": "stdout",
162 "text": "Starting job # 7 in a separate thread.\nWill wait for j now...\n"
347 "text": [
348 "Starting job # 7 in a separate thread.\n",
349 "Will wait for j now...\n"
350 ]
163 351 },
164 352 {
165 353 "output_type": "stream",
166 354 "stream": "stdout",
167 "text": "Result from j:\n"
355 "text": [
356 "Result from j:\n"
357 ]
168 358 },
169 359 {
170 360 "output_type": "pyout",
171 361 "prompt_number": 46,
172 "text": "{&apos;args&apos;: (), &apos;interval&apos;: 2, &apos;kwargs&apos;: {}}"
362 "text": [
363 "{&apos;args&apos;: (), &apos;interval&apos;: 2, &apos;kwargs&apos;: {}}"
364 ]
173 365 }
174 366 ],
175 "collapsed": false,
176 "prompt_number": 46,
177 "input": "j = jobs.new(sleepfunc, 2)\nprint \"Will wait for j now...\"\nsys.stdout.flush()\nj.join()\nprint \"Result from j:\"\nj.result"
367 "prompt_number": 46
178 368 },
179 369 {
180 "input": "",
181 370 "cell_type": "code",
182 371 "collapsed": true,
372 "input": [],
183 373 "language": "python",
374 "metadata": {},
184 375 "outputs": []
185 376 }
186 ]
187 }
188 377 ],
189 "metadata": {
190 "name": "BackgroundJobs"
191 },
192 "nbformat": 2
378 "metadata": {}
379 }
380 ]
193 381 } No newline at end of file
@@ -1,228 +1,308 b''
1 1 {
2 "nbformat": 2,
3 2 "metadata": {
4 3 "name": "rmt"
5 4 },
5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
10 "source": "# Eigenvalue distribution of Gaussian orthogonal random matrices",
11 "cell_type": "markdown"
11 "cell_type": "markdown",
12 "metadata": {},
13 "source": [
14 "# Eigenvalue distribution of Gaussian orthogonal random matrices"
15 ]
12 16 },
13 17 {
14 "source": "The eigenvalues of random matrices obey certain statistical laws. Here we construct random matrices \nfrom the Gaussian Orthogonal Ensemble (GOE), find their eigenvalues and then investigate the nearest\nneighbor eigenvalue distribution $\\rho(s)$.",
15 "cell_type": "markdown"
18 "cell_type": "markdown",
19 "metadata": {},
20 "source": [
21 "The eigenvalues of random matrices obey certain statistical laws. Here we construct random matrices \n",
22 "from the Gaussian Orthogonal Ensemble (GOE), find their eigenvalues and then investigate the nearest\n",
23 "neighbor eigenvalue distribution $\\rho(s)$."
24 ]
16 25 },
17 26 {
18 27 "cell_type": "code",
28 "collapsed": false,
29 "input": [
30 "from rmtkernel import ensemble_diffs, normalize_diffs, GOE\n",
31 "import numpy as np\n",
32 "from IPython.parallel import Client"
33 ],
19 34 "language": "python",
35 "metadata": {},
20 36 "outputs": [],
21 "collapsed": false,
22 "prompt_number": 1,
23 "input": "from rmtkernel import ensemble_diffs, normalize_diffs, GOE\nimport numpy as np\nfrom IPython.parallel import Client"
37 "prompt_number": 1
24 38 },
25 39 {
26 "source": "## Wigner's nearest neighbor eigenvalue distribution",
27 "cell_type": "markdown"
40 "cell_type": "markdown",
41 "metadata": {},
42 "source": [
43 "## Wigner's nearest neighbor eigenvalue distribution"
44 ]
28 45 },
29 46 {
30 "source": "The Wigner distribution gives the theoretical result for the nearest neighbor eigenvalue distribution\nfor the GOE:\n\n$$\\rho(s) = \\frac{\\pi s}{2} \\exp(-\\pi s^2/4)$$",
31 "cell_type": "markdown"
47 "cell_type": "markdown",
48 "metadata": {},
49 "source": [
50 "The Wigner distribution gives the theoretical result for the nearest neighbor eigenvalue distribution\n",
51 "for the GOE:\n",
52 "\n",
53 "$$\\rho(s) = \\frac{\\pi s}{2} \\exp(-\\pi s^2/4)$$"
54 ]
32 55 },
33 56 {
34 57 "cell_type": "code",
58 "collapsed": true,
59 "input": [
60 "def wigner_dist(s):\n",
61 " \"\"\"Returns (s, rho(s)) for the Wigner GOE distribution.\"\"\"\n",
62 " return (np.pi*s/2.0) * np.exp(-np.pi*s**2/4.)"
63 ],
35 64 "language": "python",
65 "metadata": {},
36 66 "outputs": [],
37 "collapsed": true,
38 "prompt_number": 2,
39 "input": "def wigner_dist(s):\n \"\"\"Returns (s, rho(s)) for the Wigner GOE distribution.\"\"\"\n return (np.pi*s/2.0) * np.exp(-np.pi*s**2/4.)"
67 "prompt_number": 2
40 68 },
41 69 {
42 70 "cell_type": "code",
71 "collapsed": true,
72 "input": [
73 "def generate_wigner_data():\n",
74 " s = np.linspace(0.0,4.0,400)\n",
75 " rhos = wigner_dist(s)\n",
76 " return s, rhos"
77 ],
43 78 "language": "python",
79 "metadata": {},
44 80 "outputs": [],
45 "collapsed": true,
46 "prompt_number": 3,
47 "input": "def generate_wigner_data():\n s = np.linspace(0.0,4.0,400)\n rhos = wigner_dist(s)\n return s, rhos"
81 "prompt_number": 3
48 82 },
49 83 {
50 84 "cell_type": "code",
85 "collapsed": false,
86 "input": [
87 "s, rhos = generate_wigner_data()"
88 ],
51 89 "language": "python",
90 "metadata": {},
52 91 "outputs": [],
53 "collapsed": false,
54 "prompt_number": 4,
55 "input": "s, rhos = generate_wigner_data()"
92 "prompt_number": 4
56 93 },
57 94 {
58 95 "cell_type": "code",
96 "collapsed": false,
97 "input": [
98 "plot(s, rhos)\n",
99 "xlabel('Normalized level spacing s')\n",
100 "ylabel('Probability $\\rho(s)$')"
101 ],
59 102 "language": "python",
103 "metadata": {},
60 104 "outputs": [
61 105 {
62 106 "output_type": "pyout",
63 107 "prompt_number": 17,
64 "text": "&lt;matplotlib.text.Text at 0x3828790&gt;"
108 "text": [
109 "&lt;matplotlib.text.Text at 0x3828790&gt;"
110 ]
65 111 },
66 112 {
67 113 "output_type": "display_data",
68 114 "png": "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\nSUVORK5CYII=\n"
69 115 }
70 116 ],
71 "collapsed": false,
72 "prompt_number": 17,
73 "input": "plot(s, rhos)\nxlabel('Normalized level spacing s')\nylabel('Probability $\\rho(s)$')"
117 "prompt_number": 17
74 118 },
75 119 {
76 "source": "## Serial calculation of nearest neighbor eigenvalue distribution",
77 "cell_type": "markdown"
120 "cell_type": "markdown",
121 "metadata": {},
122 "source": [
123 "## Serial calculation of nearest neighbor eigenvalue distribution"
124 ]
78 125 },
79 126 {
80 "source": "In this section we numerically construct and diagonalize a large number of GOE random matrices\nand compute the nerest neighbor eigenvalue distribution. This comptation is done on a single core.",
81 "cell_type": "markdown"
127 "cell_type": "markdown",
128 "metadata": {},
129 "source": [
130 "In this section we numerically construct and diagonalize a large number of GOE random matrices\n",
131 "and compute the nerest neighbor eigenvalue distribution. This comptation is done on a single core."
132 ]
82 133 },
83 134 {
84 135 "cell_type": "code",
136 "collapsed": true,
137 "input": [
138 "def serial_diffs(num, N):\n",
139 " \"\"\"Compute the nearest neighbor distribution for num NxX matrices.\"\"\"\n",
140 " diffs = ensemble_diffs(num, N)\n",
141 " normalized_diffs = normalize_diffs(diffs)\n",
142 " return normalized_diffs"
143 ],
85 144 "language": "python",
145 "metadata": {},
86 146 "outputs": [],
87 "collapsed": true,
88 "prompt_number": 6,
89 "input": "def serial_diffs(num, N):\n \"\"\"Compute the nearest neighbor distribution for num NxX matrices.\"\"\"\n diffs = ensemble_diffs(num, N)\n normalized_diffs = normalize_diffs(diffs)\n return normalized_diffs"
147 "prompt_number": 6
90 148 },
91 149 {
92 150 "cell_type": "code",
151 "collapsed": true,
152 "input": [
153 "serial_nmats = 1000\n",
154 "serial_matsize = 50"
155 ],
93 156 "language": "python",
157 "metadata": {},
94 158 "outputs": [],
95 "collapsed": true,
96 "prompt_number": 7,
97 "input": "serial_nmats = 1000\nserial_matsize = 50"
159 "prompt_number": 7
98 160 },
99 161 {
100 162 "cell_type": "code",
163 "collapsed": false,
164 "input": [
165 "%timeit -r1 -n1 serial_diffs(serial_nmats, serial_matsize)"
166 ],
101 167 "language": "python",
168 "metadata": {},
102 169 "outputs": [
103 170 {
104 171 "output_type": "stream",
105 "text": "1 loops, best of 1: 1.19 s per loop"
172 "stream": "stdout",
173 "text": [
174 "1 loops, best of 1: 1.19 s per loop"
175 ]
106 176 }
107 177 ],
108 "collapsed": false,
109 "prompt_number": 8,
110 "input": "%timeit -r1 -n1 serial_diffs(serial_nmats, serial_matsize)"
178 "prompt_number": 8
111 179 },
112 180 {
113 181 "cell_type": "code",
182 "collapsed": false,
183 "input": [
184 "serial_diffs = serial_diffs(serial_nmats, serial_matsize)"
185 ],
114 186 "language": "python",
187 "metadata": {},
115 188 "outputs": [],
116 "collapsed": false,
117 "prompt_number": 9,
118 "input": "serial_diffs = serial_diffs(serial_nmats, serial_matsize)"
189 "prompt_number": 9
119 190 },
120 191 {
121 "source": "The numerical computation agrees with the predictions of Wigner, but it would be nice to get more\nstatistics. For that we will do a parallel computation.",
122 "cell_type": "markdown"
192 "cell_type": "markdown",
193 "metadata": {},
194 "source": [
195 "The numerical computation agrees with the predictions of Wigner, but it would be nice to get more\n",
196 "statistics. For that we will do a parallel computation."
197 ]
123 198 },
124 199 {
125 200 "cell_type": "code",
201 "collapsed": false,
202 "input": [
203 "hist_data = hist(serial_diffs, bins=30, normed=True)\n",
204 "plot(s, rhos)\n",
205 "xlabel('Normalized level spacing s')\n",
206 "ylabel('Probability $P(s)$')"
207 ],
126 208 "language": "python",
209 "metadata": {},
127 210 "outputs": [
128 211 {
129 212 "output_type": "pyout",
130 213 "prompt_number": 10,
131 "text": "&lt;matplotlib.text.Text at 0x3475bd0&gt;"
214 "text": [
215 "&lt;matplotlib.text.Text at 0x3475bd0&gt;"
216 ]
132 217 },
133 218 {
134 219 "output_type": "display_data",
135 220 "png": "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\nvDyaNWtGcHAwzZs3N7u/dUNyat2XJSk81FTR/rToO+4JIYQwHbM+JCWEEMJ8SMEQQghhECkYQggh\nDCIFQwghhEGkYIhKZWNjQ3BwsP75v//977/cArTq+fv7c/jwYQACAwNJTU2t0PrCw8MZOnSowa9X\nxbaq0tWrV3nmmWdMuk1hmaRgiEpVs2ZNvv/+e5KSkgDjr8TNy8urcIZ7t7l161bs7e0rvE5r1qJF\nCzZu3Kh1DGEBpGCISmVnZ8cLL7zAokWLii27evUqM2fOxNPTk1mzZnHjxg0AJkyYwMsvv4yvry+v\nvvoqEydO5JVXXsHHx4f27dtz5MgRXnjhBTp06MC8efP06/v73/9O165d6dGjB6tXry4xj7OzM0lJ\nSXz00Ud4e3vj7e1NmzZtePzxx4GCecDGjRuHr68vc+bM0V+RGxsbS9++ffH29mb79u1lfu6MjAw+\n/PBD/Pz8CAwMJDw8HIDu3bsXuZq2cO8nMzOzxPaluXz5MoMGDcLLywtPT0/OnTtHXFwc7u7uTJ48\nGTc3N+bPn6/P//bbb+Pj40PXrl1ZsGBBkfW88soreHt706VLFy5cuEBcXBwdO3YE4IsvvmD06NEM\nHjwYDw8Pli5dqn/vtm3b6N69Oz4+Prz00ktMnz69WM6jR4/St29fvLy86Ny5M7dv3y6z74QFqcjU\nuUL8Vb169VRqaqpydnZWKSkp6t///reaN2+eUkqpWbNmqffff18ppdSCBQvU7NmzlVJKjR8/Xvn5\n+emn3J4wYYIaNGiQysrKUl988YWqV6+eCg8PV1lZWcrNzU0/dXxycrJSSqmsrCzl6+urbt++rZRS\nyt/fXx06dEgppZSzs7NKSkrS58vJyVG9e/dWoaGh+ra3bt1SSik1e/Zs9c033yillOrUqZOKjo5W\nt2/fVgMHDixxeujdu3fr7zPw+eefqyVLliillLp+/bry8fFRSim1aNEiNXfuXKWUUlevXlXt27e/\nb/t713mvuXPnqk8++UT/GTIyMtSFCxeUTqdT3333ncrMzFRPP/20+vbbb4v0TW5urho6dKg6deqU\nvq9XrFih77c7d+6oCxcu6KeS//zzz1WTJk3U1atXVWpqqnrooYdUdna2ysnJUc7OzurChQsqKSlJ\nde7cWU2fPr1YzvHjx6uwsDClVME04Lm5ucXaCMslexii0tWvX59x48YV+dcpwM8//8ykSZMAmDx5\nMlu2bAEKDiGNGDGC+vXr69uOGDGCmjVr0r17dxo2bIifnx81a9bE29tbPxPwzp07CQwMxNvbm/Pn\nz/PLL7+UmW3GjBn07duXwMBADh06xLFjx/D398fb25vQ0FAiIyO5cuUKSil8fHyoW7cuo0aNKnO6\n6k2bNrF69Wq8vb0ZOHAgN27c4MKFC4wcOZJvv/0WgA0bNujHCkpqf/78+VLX37VrVxYvXsx7771H\ncnIyDzzwAFAwLc2wYcOoVasWY8aMYdu2bQAcPHiQ4cOH06lTJw4fPsyOHTvIzs5m9+7dTJkyBSg4\nfFi7du1i2xowYADNmzenfv36uLu7c/jwYaKioujYsSPOzs44ODjwxBNPlNgn3bt3Z86cOSxfvpzc\n3FxsbW3L/J0Iy2H2U4MIy/TSSy/RuXNnJk6cWOT10r54mzdvXuR54fxcNWvWpGHDhvrXa9asSXZ2\nNmlpacyZM4c9e/bw4IMPMmzYMG7evHnfTF988QWXL19m5cqVQME01R4eHuzevbtIu/j4eMM+5D3y\n8/NZsWIFffr0KbascePG/P7772zYsEE/NUNp7Qun6/irwMBAunTpwpo1a+jZsycbN24s0i+FCsdv\npk+fzrfffouHhwezZs3i5s2b6HS6Emco/au/9ndmZiY1atQoMjZU2jqCgoLo37+/fiqS6OhomjZt\net/tCcshexiiSjRq1IiRI0fy6aef6r9oBg8ezJdffkl+fj6fffYZTzzxRLnWrZTi1q1b2NnZ0axZ\nM06fPs2uXbvu+55Dhw6xcOFCvvrqK/1rXbt25caNG/o9lvT0dM6cOcNDDz2Era0tsbGxpKens2HD\nhjIzjR07lpCQENLS0gCKTHk9atQo3nvvPVJTU/Hw8CizfUkuXLign7uob9+++nGRlJQUfvjhB7Ky\nsli/fj0DBw4kMzOTtLQ0nJ2duXLlCps3bwYKxpcee+wxVq9ejVKKrKwsMjIyyvxsOp2Obt268fvv\nvxMXF0dycjKhoaElntBw7tw5XFxc+N///V9cXV3N4l4lovJIwRCV6t4vkVdeeYXExET98+DgYC5d\nuoS3tzc3btzg5ZdfLvF9f31e0rKWLVsyfPhwPDw8mDZtWqmnohb+q3rFihXcvHmTxx57DG9vb154\n4QUAvvrqK1atWkWnTp3o0aMHf/zxBwAff/wxr732Gr169cLT07PEL0edTqd/fcSIEfj4+BAQEICH\nhwdz587VtxsxYgTr169n5MiRRV4rqf2967zXhg0b8PDwoGvXrty5c0e/LldXV3788Ue8vLzw8PAg\nMDCQBx54gDlz5uDj48OoUaMYPHiwfj3vvPMOZ8+exdPTk549e+pPPCjcZmnbt7W1Zfny5YwaNYqB\nAwfSsWNH2rRpU6zdkiVL6NixIz4+Pri6utKjR48Sfy/CMsnkg0JYqLi4OIYOHcrvv/9uku2lp6dT\nt25dUlJSGDJkCJ988gnt27c3ybaFeZAxDCEsmCnvODdv3jzCwsKws7Pj2WeflWJRDckehhBCCIPI\nGIYQQgiDSMEQQghhECkYQgghDCIFQwghhEGkYAghhDCIFAwhhBAG+X8LAxP1Be5fBAAAAABJRU5E\nrkJggg==\n"
136 221 }
137 222 ],
138 "collapsed": false,
139 "prompt_number": 10,
140 "input": "hist_data = hist(serial_diffs, bins=30, normed=True)\nplot(s, rhos)\nxlabel('Normalized level spacing s')\nylabel('Probability $P(s)$')"
223 "prompt_number": 10
141 224 },
142 225 {
143 "source": "## Parallel calculation of nearest neighbor eigenvalue distribution",
144 "cell_type": "markdown"
226 "cell_type": "markdown",
227 "metadata": {},
228 "source": [
229 "## Parallel calculation of nearest neighbor eigenvalue distribution"
230 ]
145 231 },
146 232 {
147 "source": "Here we perform a parallel computation, where each process constructs and diagonalizes a subset of\nthe overall set of random matrices.",
148 "cell_type": "markdown"
233 "cell_type": "markdown",
234 "metadata": {},
235 "source": [
236 "Here we perform a parallel computation, where each process constructs and diagonalizes a subset of\n",
237 "the overall set of random matrices."
238 ]
149 239 },
150 240 {
151 241 "cell_type": "code",
242 "collapsed": true,
243 "input": [
244 "def parallel_diffs(rc, num, N):\n",
245 " nengines = len(rc.targets)\n",
246 " num_per_engine = num/nengines\n",
247 " print \"Running with\", num_per_engine, \"per engine.\"\n",
248 " ar = rc.apply_async(ensemble_diffs, num_per_engine, N)\n",
249 " diffs = np.array(ar.get()).flatten()\n",
250 " normalized_diffs = normalize_diffs(diffs)\n",
251 " return normalized_diffs"
252 ],
152 253 "language": "python",
254 "metadata": {},
153 255 "outputs": [],
154 "collapsed": true,
155 "prompt_number": 11,
156 "input": "def parallel_diffs(rc, num, N):\n nengines = len(rc.targets)\n num_per_engine = num/nengines\n print \"Running with\", num_per_engine, \"per engine.\"\n ar = rc.apply_async(ensemble_diffs, num_per_engine, N)\n diffs = np.array(ar.get()).flatten()\n normalized_diffs = normalize_diffs(diffs)\n return normalized_diffs"
256 "prompt_number": 11
157 257 },
158 258 {
159 259 "cell_type": "code",
260 "collapsed": true,
261 "input": [
262 "client = Client()\n",
263 "view = client[:]\n",
264 "view.run('rmtkernel.py')\n",
265 "view.block = False"
266 ],
160 267 "language": "python",
268 "metadata": {},
161 269 "outputs": [],
162 "collapsed": true,
163 "prompt_number": 12,
164 "input": "client = Client()\nview = client[:]\nview.run('rmtkernel.py')\nview.block = False"
270 "prompt_number": 12
165 271 },
166 272 {
167 273 "cell_type": "code",
274 "collapsed": true,
275 "input": [
276 "parallel_nmats = 40*serial_nmats\n",
277 "parallel_matsize = 50"
278 ],
168 279 "language": "python",
280 "metadata": {},
169 281 "outputs": [],
170 "collapsed": true,
171 "prompt_number": 13,
172 "input": "parallel_nmats = 40*serial_nmats\nparallel_matsize = 50"
282 "prompt_number": 13
173 283 },
174 284 {
175 285 "cell_type": "code",
176 "language": "python",
177 "outputs": [
178 {
179 "output_type": "stream",
180 "text": "Running with 10000 per engine.\n1 loops, best of 1: 14 s per loop"
181 },
182 {
183 "output_type": "stream"
184 }
185 ],
186 286 "collapsed": false,
187 "prompt_number": 14,
188 "input": "%timeit -r1 -n1 parallel_diffs(view, parallel_nmats, parallel_matsize)"
189 },
190 {
191 "cell_type": "code",
287 "input": [
288 "%timeit -r1 -n1 parallel_diffs(view, parallel_nmats, parallel_matsize)"
289 ],
192 290 "language": "python",
291 "metadata": {},
193 292 "outputs": [
194 293 {
195 294 "output_type": "stream",
196 "text": "Running with 10000 per engine."
295 "stream": "stdout",
296 "text": [
297 "Running with 10000 per engine.\n",
298 "1 loops, best of 1: 14 s per loop"
299 ]
197 300 }
198 301 ],
199 "collapsed": false,
200 "prompt_number": 15,
201 "input": "pdiffs = parallel_diffs(view, parallel_nmats, parallel_matsize)"
202 },
203 {
204 "source": "Again, the agreement with the Wigner distribution is excellent, but now we have better\nstatistics.",
205 "cell_type": "markdown"
206 },
207 {
208 "cell_type": "code",
209 "language": "python",
210 "outputs": [
211 {
212 "output_type": "pyout",
213 "prompt_number": 16,
214 "text": "&lt;matplotlib.text.Text at 0x376c950&gt;"
215 },
216 {
217 "output_type": "display_data",
218 "png": "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\n"
302 "prompt_number": 14
219 303 }
220 304 ],
221 "collapsed": false,
222 "prompt_number": 16,
223 "input": "hist_data = hist(pdiffs, bins=30, normed=True)\nplot(s, rhos)\nxlabel('Normalized level spacing s')\nylabel('Probability $P(s)$')"
224 }
225 ]
305 "metadata": {}
226 306 }
227 307 ]
228 308 } No newline at end of file
@@ -2,17 +2,19 b''
2 2 "metadata": {
3 3 "name": "gilsleep"
4 4 },
5 "nbformat": 2,
5 "nbformat": 3,
6 "nbformat_minor": 0,
6 7 "worksheets": [
7 8 {
8 9 "cells": [
9 10 {
10 11 "cell_type": "markdown",
12 "metadata": {},
11 13 "source": [
12 "Holding the GIL for too long could disrupt the heartbeat due to non-copying sends.",
13 "",
14 "The following cell repeatedly calls a function that holds the GIL for five seconds.",
15 "",
14 "Holding the GIL for too long could disrupt the heartbeat due to non-copying sends.\n",
15 "\n",
16 "The following cell repeatedly calls a function that holds the GIL for five seconds.\n",
17 "\n",
16 18 "The heartbeat will fail after a few iterations prior to fixing Issue [#1260](https://github.com/ipython/ipython/issues/1260)."
17 19 ]
18 20 },
@@ -20,25 +22,26 b''
20 22 "cell_type": "code",
21 23 "collapsed": false,
22 24 "input": [
23 "import sys",
24 "import time",
25 "",
26 "from cython import inline",
27 "",
28 "def gilsleep(t):",
29 " \"\"\"gil-holding sleep with cython.inline\"\"\"",
30 " code = '\\n'.join([",
31 " 'from posix cimport unistd',",
32 " 'unistd.sleep(t)',",
33 " ])",
34 " while True:",
35 " inline(code, quiet=True, t=t)",
36 " print time.time()",
37 " sys.stdout.flush() # this is important",
38 "",
25 "import sys\n",
26 "import time\n",
27 "\n",
28 "from cython import inline\n",
29 "\n",
30 "def gilsleep(t):\n",
31 " \"\"\"gil-holding sleep with cython.inline\"\"\"\n",
32 " code = '\\n'.join([\n",
33 " 'from posix cimport unistd',\n",
34 " 'unistd.sleep(t)',\n",
35 " ])\n",
36 " while True:\n",
37 " inline(code, quiet=True, t=t)\n",
38 " print time.time()\n",
39 " sys.stdout.flush() # this is important\n",
40 "\n",
39 41 "gilsleep(5)"
40 42 ],
41 43 "language": "python",
44 "metadata": {},
42 45 "outputs": [],
43 46 "prompt_number": 1
44 47 },
@@ -47,10 +50,12 b''
47 50 "collapsed": true,
48 51 "input": [],
49 52 "language": "python",
53 "metadata": {},
50 54 "outputs": [],
51 55 "prompt_number": "&nbsp;"
52 56 }
53 ]
57 ],
58 "metadata": {}
54 59 }
55 60 ]
56 61 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now