Skip to content

Commit 154ca85

Browse files
committed
update for jupyterlite
1 parent 5f86700 commit 154ca85

1 file changed

Lines changed: 69 additions & 155 deletions

File tree

docs/11_performance.ipynb

Lines changed: 69 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,51 @@
88
"\n",
99
"**Scott Prahl**\n",
1010
"\n",
11-
"**Feb 2025**\n",
11+
"**Jan 2026**\n",
1212
"\n",
13-
"Unfortunately, switching between jit and non-jit during runtime is too complicated when combined with numba caching."
13+
"Switching between jit and non-jit during runtime is too complicated when combined with numba caching. Each run must be set up beforehand.\n",
14+
"\n",
15+
"The results from my computer for the first test are indicative of speedups. The jitted version that uses numba is about 30x faster than the non-jitted version and 60x faster than the same code running under JupyterLite\n",
16+
"\n",
17+
"| Array size | JIT (µs) | Non-JIT (µs) | JupyterLite (µs) |\n",
18+
"| ---------: | -------: | -----------: | ---------------: |\n",
19+
"| 1 | 1.8 | 32.3 | 46.8 |\n",
20+
"| 3 | 4.9 | 151 | 246 |\n",
21+
"| 15 | 22.2 | 790 | 1290 |\n",
22+
"| 63 | 90.9 | 3320 | 5350 |\n",
23+
"| 251 | 347 | 12800 | 21300 |\n",
24+
"| 1000 | 1360 | 49000 | 88000 |\n"
1425
]
1526
},
1627
{
1728
"cell_type": "code",
18-
"execution_count": 4,
29+
"execution_count": 1,
1930
"metadata": {},
2031
"outputs": [],
2132
"source": [
2233
"import os\n",
34+
"import sys\n",
2335
"import tempfile\n",
2436
"import numpy as np\n",
2537
"\n",
26-
"os.environ[\"MIEPYTHON_USE_JIT\"] = \"1\" # Set to \"0\" to disable JIT\n",
27-
"os.environ[\"NUMBA_CACHE_DIR\"] = tempfile.gettempdir()\n",
38+
"if sys.platform == \"emscripten\":\n",
39+
" import piplite\n",
2840
"\n",
29-
"import miepython as mie"
41+
" await piplite.install(\"miepython\")\n",
42+
" os.environ[\"MIEPYTHON_USE_JIT\"] = \"0\" # jupyterlite cannot use numba\n",
43+
"else:\n",
44+
" os.environ[\"MIEPYTHON_USE_JIT\"] = \"0\" # Set to \"0\" to disable JIT\n",
45+
" os.environ[\"NUMBA_CACHE_DIR\"] = tempfile.gettempdir()\n",
46+
" \n",
47+
"import miepython as mie\n",
48+
"\n",
49+
"def print_header():\n",
50+
" if sys.platform == \"emscripten\":\n",
51+
" print('JupyterLite results:')\n",
52+
" elif os.environ[\"MIEPYTHON_USE_JIT\"]=='0':\n",
53+
" print('Non-jitted results:')\n",
54+
" else:\n",
55+
" print('Jitted results:')"
3056
]
3157
},
3258
{
@@ -40,19 +66,20 @@
4066
},
4167
{
4268
"cell_type": "code",
43-
"execution_count": 6,
69+
"execution_count": 2,
4470
"metadata": {},
4571
"outputs": [
4672
{
4773
"name": "stdout",
4874
"output_type": "stream",
4975
"text": [
50-
"1.71 μs ± 23.7 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n",
51-
"5.62 μs ± 156 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
52-
"25.4 μs ± 790 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
53-
"105 μs ± 558 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
54-
"407 μs ± 3.32 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n",
55-
"1.63 ms ± 46 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n"
76+
"Non-jitted results:\n",
77+
"28.6 μs ± 504 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
78+
"142 μs ± 3.04 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
79+
"775 μs ± 16.1 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n",
80+
"3.22 ms ± 67.3 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
81+
"12.5 ms ± 284 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
82+
"51.9 ms ± 1.58 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
5683
]
5784
}
5885
],
@@ -64,27 +91,11 @@
6491
"result = np.zeros(ntests)\n",
6592
"resultj = np.zeros(ntests)\n",
6693
"\n",
94+
"print_header()\n",
6795
"for i in range(ntests):\n",
6896
" x = np.linspace(0.1, 20, N[i])\n",
6997
" a = %timeit -o qext, qsca, qback, g = mie.efficiencies_mx(m,x)\n",
70-
" result[i] = a.best\n",
71-
"\n",
72-
"# mie.use_numba(True) # Ensure the JIT backend is used\n",
73-
"# for i in range(ntests):\n",
74-
"# x = np.linspace(0.1, 20, N[i])\n",
75-
"# a = %timeit -o qext, qsca, qback, g = mie.efficiencies_mx(m,x)\n",
76-
"# resultj[i] = a.best\n",
77-
"\n",
78-
"# improvement = result / resultj\n",
79-
"# plt.loglog(N, resultj, \":r\")\n",
80-
"# plt.loglog(N, result, \":b\")\n",
81-
"# plt.loglog(N, resultj, \"or\", label=\"jit\")\n",
82-
"# plt.loglog(N, result, \"ob\", label=\"no jit\")\n",
83-
"# plt.legend()\n",
84-
"# plt.xlabel(\"Number of sphere sizes calculated\")\n",
85-
"# plt.ylabel(\"Execution Time\")\n",
86-
"# plt.title(\"Jit improvement is %d to %dX\" % (np.min(improvement), np.max(improvement)))\n",
87-
"# plt.show()"
98+
" result[i] = a.best"
8899
]
89100
},
90101
{
@@ -96,19 +107,19 @@
96107
},
97108
{
98109
"cell_type": "code",
99-
"execution_count": 8,
110+
"execution_count": 3,
100111
"metadata": {},
101112
"outputs": [
102113
{
103114
"name": "stdout",
104115
"output_type": "stream",
105116
"text": [
106-
"2.85 μs ± 111 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
107-
"5.81 μs ± 75.1 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
108-
"25.2 μs ± 270 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
109-
"103 μs ± 1.11 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
110-
"405 μs ± 1.84 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n",
111-
"1.64 ms ± 28.3 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n"
117+
"62.7 μs ± 839 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
118+
"167 μs ± 2.25 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
119+
"846 μs ± 9.37 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n",
120+
"3.58 ms ± 70.4 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
121+
"13.9 ms ± 164 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
122+
"55.7 ms ± 1.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
112123
]
113124
}
114125
],
@@ -123,29 +134,12 @@
123134
"result = np.zeros(ntests)\n",
124135
"resultj = np.zeros(ntests)\n",
125136
"\n",
137+
"print_header()\n",
126138
"for i in range(ntests):\n",
127139
" lambda0 = np.linspace(300, 800, N[i]) # also in nm\n",
128140
" xx = 2 * np.pi * r * mwater / lambda0\n",
129141
" a = %timeit -o qext, qsca, qback, g = mie.efficiencies_mx(mm,xx)\n",
130-
" result[i] = a.best\n",
131-
"\n",
132-
"# mie.use_numba(True) # Ensure the JIT backend is used\n",
133-
"# for i in range(ntests):\n",
134-
"# lambda0 = np.linspace(300, 800, N[i]) # also in nm\n",
135-
"# xx = 2 * np.pi * r * mwater / lambda0\n",
136-
"# a = %timeit -o qext, qsca, qback, g = mie.efficiencies_mx(mm,xx)\n",
137-
"# resultj[i] = a.best\n",
138-
"\n",
139-
"# improvement = result / resultj\n",
140-
"# plt.loglog(N, resultj, \":r\")\n",
141-
"# plt.loglog(N, result, \":b\")\n",
142-
"# plt.loglog(N, resultj, \"or\", label=\"jit\")\n",
143-
"# plt.loglog(N, result, \"ob\", label=\"no jit\")\n",
144-
"# plt.legend()\n",
145-
"# plt.xlabel(\"Number of Wavelengths Calculated\")\n",
146-
"# plt.ylabel(\"Execution Time\")\n",
147-
"# plt.title(\"Jit improvement is %d to %dX\" % (np.min(improvement), np.max(improvement)))\n",
148-
"# plt.show()"
142+
" result[i] = a.best"
149143
]
150144
},
151145
{
@@ -159,19 +153,19 @@
159153
},
160154
{
161155
"cell_type": "code",
162-
"execution_count": 9,
156+
"execution_count": 4,
163157
"metadata": {},
164158
"outputs": [
165159
{
166160
"name": "stdout",
167161
"output_type": "stream",
168162
"text": [
169-
"3.61 μs ± 27.9 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
170-
"6.88 μs ± 60.8 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
171-
"26.3 μs ± 167 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
172-
"106 μs ± 2.52 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
173-
"407 μs ± 4.93 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n",
174-
"1.61 ms ± 14.3 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n"
163+
"66.4 μs ± 470 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
164+
"175 μs ± 1.52 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
165+
"851 μs ± 13.1 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n",
166+
"3.48 ms ± 24.1 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
167+
"13.8 ms ± 120 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n",
168+
"55.1 ms ± 1.3 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
175169
]
176170
}
177171
],
@@ -184,27 +178,11 @@
184178
"result = np.zeros(ntests)\n",
185179
"resultj = np.zeros(ntests)\n",
186180
"\n",
181+
"print_header()\n",
187182
"for i in range(ntests):\n",
188183
" lambda0 = np.linspace(300, 800, N[i]) # also in nm\n",
189184
" a = %timeit -o qext, qsca, qback, g = mie.efficiencies(m_sphere, d, lambda0, n_water)\n",
190-
" result[i] = a.best\n",
191-
"\n",
192-
"# mie.use_numba(True) # Ensure the JIT backend is used\n",
193-
"# for i in range(ntests):\n",
194-
"# lambda0 = np.linspace(300, 800, N[i]) # also in nm\n",
195-
"# a = %timeit -o qext, qsca, qback, g = mie.efficiencies(m_sphere, d, lambda0, n_water)\n",
196-
"# resultj[i] = a.best\n",
197-
"\n",
198-
"# improvement = result / resultj\n",
199-
"# plt.loglog(N, resultj, \":r\")\n",
200-
"# plt.loglog(N, result, \":b\")\n",
201-
"# plt.loglog(N, resultj, \"or\", label=\"jit\")\n",
202-
"# plt.loglog(N, result, \"ob\", label=\"no jit\")\n",
203-
"# plt.legend()\n",
204-
"# plt.xlabel(\"Number of Wavelengths Calculated\")\n",
205-
"# plt.ylabel(\"Execution Time\")\n",
206-
"# plt.title(\"Jit improvement is %d to %dX\" % (np.min(improvement), np.max(improvement)))\n",
207-
"# plt.show()"
185+
" result[i] = a.best"
208186
]
209187
},
210188
{
@@ -216,24 +194,11 @@
216194
},
217195
{
218196
"cell_type": "code",
219-
"execution_count": 10,
197+
"execution_count": null,
220198
"metadata": {
221199
"tags": []
222200
},
223-
"outputs": [
224-
{
225-
"name": "stdout",
226-
"output_type": "stream",
227-
"text": [
228-
"4.35 μs ± 100 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
229-
"4.12 μs ± 41.3 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
230-
"5.19 μs ± 64.3 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
231-
"8.71 μs ± 129 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
232-
"23.2 μs ± 264 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
233-
"81.7 μs ± 877 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n"
234-
]
235-
}
236-
],
201+
"outputs": [],
237202
"source": [
238203
"ntests = 6\n",
239204
"m = 1.5\n",
@@ -243,28 +208,12 @@
243208
"result = np.zeros(ntests)\n",
244209
"resultj = np.zeros(ntests)\n",
245210
"\n",
211+
"print_header()\n",
246212
"for i in range(ntests):\n",
247213
" theta = np.linspace(-180, 180, N[i])\n",
248214
" mu = np.cos(theta / 180 * np.pi)\n",
249215
" a = %timeit -o s1, s2 = mie.S1_S2(m,x,mu)\n",
250-
" result[i] = a.best\n",
251-
"\n",
252-
"# for i in range(ntests):\n",
253-
"# theta = np.linspace(-180, 180, N[i])\n",
254-
"# mu = np.cos(theta / 180 * np.pi)\n",
255-
"# a = %timeit -o s1, s2 = mie.S1_S2(m,x,mu)\n",
256-
"# resultj[i] = a.best\n",
257-
"\n",
258-
"# improvement = result / resultj\n",
259-
"# plt.loglog(N, resultj, \":r\")\n",
260-
"# plt.loglog(N, result, \":b\")\n",
261-
"# plt.loglog(N, resultj, \"or\", label=\"jit\")\n",
262-
"# plt.loglog(N, result, \"ob\", label=\"no jit\")\n",
263-
"# plt.legend()\n",
264-
"# plt.xlabel(\"Number of Angles Calculated\")\n",
265-
"# plt.ylabel(\"Execution Time\")\n",
266-
"# plt.title(\"Jit improvement is %d to %dX\" % (np.min(improvement), np.max(improvement)))\n",
267-
"# plt.show()"
216+
" result[i] = a.best\n"
268217
]
269218
},
270219
{
@@ -276,22 +225,9 @@
276225
},
277226
{
278227
"cell_type": "code",
279-
"execution_count": 11,
228+
"execution_count": null,
280229
"metadata": {},
281-
"outputs": [
282-
{
283-
"name": "stdout",
284-
"output_type": "stream",
285-
"text": [
286-
"7.86 μs ± 100 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
287-
"12.9 μs ± 89.9 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n",
288-
"20.2 μs ± 23.5 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
289-
"42.9 μs ± 2.61 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
290-
"133 μs ± 1.75 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n",
291-
"504 μs ± 19 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n"
292-
]
293-
}
294-
],
230+
"outputs": [],
295231
"source": [
296232
"ntests = 6\n",
297233
"m = 1.5 - 0.1j\n",
@@ -302,33 +238,11 @@
302238
"theta = np.linspace(-180, 180)\n",
303239
"mu = np.cos(theta / 180 * np.pi)\n",
304240
"\n",
241+
"print_header()\n",
305242
"for i in range(ntests):\n",
306243
" a = %timeit -o s1, s2 = mie.S1_S2(m,x[i],mu)\n",
307-
" result[i] = a.best\n",
308-
"\n",
309-
"# mie.use_numba(True) # Ensure the JIT backend is used\n",
310-
"# for i in range(ntests):\n",
311-
"# a = %timeit -o s1, s2 = mie_S1_S2(m,x[i],mu)\n",
312-
"# resultj[i] = a.best\n",
313-
"\n",
314-
"# improvement = result / resultj\n",
315-
"# plt.loglog(N, resultj, \":r\")\n",
316-
"# plt.loglog(N, result, \":b\")\n",
317-
"# plt.loglog(N, resultj, \"or\", label=\"jit\")\n",
318-
"# plt.loglog(N, result, \"ob\", label=\"no jit\")\n",
319-
"# plt.legend()\n",
320-
"# plt.xlabel(\"Sphere Size Parameter\")\n",
321-
"# plt.ylabel(\"Execution Time\")\n",
322-
"# plt.title(\"Jit improvement is %d to %dX\" % (np.min(improvement), np.max(improvement)))\n",
323-
"# plt.show()"
244+
" result[i] = a.best\n"
324245
]
325-
},
326-
{
327-
"cell_type": "code",
328-
"execution_count": null,
329-
"metadata": {},
330-
"outputs": [],
331-
"source": []
332246
}
333247
],
334248
"metadata": {
@@ -347,7 +261,7 @@
347261
"name": "python",
348262
"nbconvert_exporter": "python",
349263
"pygments_lexer": "ipython3",
350-
"version": "3.11.13"
264+
"version": "3.12.12"
351265
},
352266
"toc": {
353267
"nav_menu": {},

0 commit comments

Comments
 (0)