Skip to content

Commit 509d506

Browse files
authored
docs: Website makeover (#724)
1 parent 849383e commit 509d506

File tree

200 files changed

+754
-1823
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

200 files changed

+754
-1823
lines changed
3.79 KB
Loading
4.95 KB
Loading
4.43 KB
Loading
Loading

docs/assets/images/open-book-icon.png

4.59 KB
Loading
5.38 KB
Loading

docs/changelog.md

+185-187
Large diffs are not rendered by default.

docs/completed-tasks.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Completed tasks](roadmap.md#completed-tasks)

docs/css/mkdocstrings.css

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1-
.md-tabs__link {
2-
font-weight: bold;
1+
:root {
2+
--md-primary-fg-color: #c96c08;
3+
--md-primary-fg-color--light: #94f2f7;
4+
--md-primary-fg-color--dark: #335365;
5+
}
6+
7+
.md-tabs__item {
8+
font-weight: bolder;
9+
}
10+
11+
.grid {
12+
font-weight: bolder;
13+
font-size: 160%;
14+
font-family: Georgia, serif;
315
}

docs/examples/sparse_finch.ipynb

+365
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"## Finch backend for `sparse`\n",
8+
"\n",
9+
"<a href=\"https://colab.research.google.com/github/pydata/sparse/blob/main/examples/sparse_finch.ipynb\" target=\"_blank\">\n",
10+
" <img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\" />\n",
11+
"</a> to download and run."
12+
]
13+
},
14+
{
15+
"cell_type": "code",
16+
"execution_count": null,
17+
"metadata": {},
18+
"outputs": [],
19+
"source": [
20+
"# pip install 'sparse[finch]==0.16.0a9' scipy\n",
21+
"# export SPARSE_BACKEND=Finch\n",
22+
"\n",
23+
"# let's make sure we're using Finch backend\n",
24+
"import os\n",
25+
"\n",
26+
"os.environ[\"SPARSE_BACKEND\"] = \"Finch\"\n",
27+
"CI_MODE = os.getenv(\"CI_MODE\", default=False)"
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"metadata": {},
34+
"outputs": [],
35+
"source": [
36+
"import importlib\n",
37+
"import time\n",
38+
"\n",
39+
"import sparse\n",
40+
"\n",
41+
"import matplotlib.pyplot as plt\n",
42+
"\n",
43+
"import numpy as np\n",
44+
"import scipy.sparse as sps\n",
45+
"import scipy.sparse.linalg as splin\n",
46+
"\n",
47+
"assert sparse.BackendType.Finch == sparse.BACKEND"
48+
]
49+
},
50+
{
51+
"cell_type": "code",
52+
"execution_count": null,
53+
"metadata": {},
54+
"outputs": [],
55+
"source": [
56+
"tns = sparse.asarray(np.zeros((10, 10))) # offers a no-copy constructor for NumPy as scipy.sparse inputs\n",
57+
"\n",
58+
"s1 = sparse.random((100, 10), density=0.01) # creates random COO tensor\n",
59+
"s2 = sparse.random((100, 100, 10), density=0.01)\n",
60+
"s2 = sparse.asarray(s2, format=\"csf\") # can be used to rewrite tensor to a new format\n",
61+
"\n",
62+
"result = sparse.tensordot(s1, s2, axes=([0, 1], [0, 2]))\n",
63+
"\n",
64+
"total = sparse.sum(result * result)\n",
65+
"print(total)"
66+
]
67+
},
68+
{
69+
"cell_type": "markdown",
70+
"metadata": {},
71+
"source": [
72+
"### Example: least squares - closed form"
73+
]
74+
},
75+
{
76+
"cell_type": "code",
77+
"execution_count": null,
78+
"metadata": {},
79+
"outputs": [],
80+
"source": [
81+
"y = sparse.random((100, 1), density=0.08)\n",
82+
"X = sparse.random((100, 5), density=0.08)\n",
83+
"X = sparse.asarray(X, format=\"csc\")\n",
84+
"X_lazy = sparse.lazy(X)\n",
85+
"\n",
86+
"X_X = sparse.compute(sparse.permute_dims(X_lazy, (1, 0)) @ X_lazy, verbose=True)\n",
87+
"\n",
88+
"X_X = sparse.asarray(X_X, format=\"csc\") # move back from dense to CSC format\n",
89+
"\n",
90+
"inverted = splin.inv(X_X) # dispatching to scipy.sparse.sparray\n",
91+
"\n",
92+
"b_hat = (inverted @ sparse.permute_dims(X, (1, 0))) @ y\n",
93+
"\n",
94+
"print(b_hat.todense())"
95+
]
96+
},
97+
{
98+
"cell_type": "markdown",
99+
"metadata": {},
100+
"source": [
101+
"## Benchmark plots"
102+
]
103+
},
104+
{
105+
"cell_type": "code",
106+
"execution_count": null,
107+
"metadata": {},
108+
"outputs": [],
109+
"source": [
110+
"ITERS = 3\n",
111+
"rng = np.random.default_rng(0)"
112+
]
113+
},
114+
{
115+
"cell_type": "code",
116+
"execution_count": null,
117+
"metadata": {},
118+
"outputs": [],
119+
"source": [
120+
"plt.style.use(\"seaborn-v0_8\")\n",
121+
"plt.rcParams[\"figure.dpi\"] = 400\n",
122+
"plt.rcParams[\"figure.figsize\"] = [8, 4]"
123+
]
124+
},
125+
{
126+
"cell_type": "code",
127+
"execution_count": null,
128+
"metadata": {},
129+
"outputs": [],
130+
"source": [
131+
"def benchmark(func, info, args) -> float:\n",
132+
" start = time.time()\n",
133+
" for _ in range(ITERS):\n",
134+
" func(*args)\n",
135+
" elapsed = time.time() - start\n",
136+
" return elapsed / ITERS"
137+
]
138+
},
139+
{
140+
"cell_type": "code",
141+
"execution_count": null,
142+
"metadata": {},
143+
"outputs": [],
144+
"source": [
145+
"print(\"MTTKRP Example:\\n\")\n",
146+
"\n",
147+
"os.environ[sparse._ENV_VAR_NAME] = \"Numba\"\n",
148+
"importlib.reload(sparse)\n",
149+
"\n",
150+
"configs = [\n",
151+
" {\"I_\": 100, \"J_\": 25, \"K_\": 10, \"L_\": 10, \"DENSITY\": 0.001},\n",
152+
" {\"I_\": 100, \"J_\": 25, \"K_\": 100, \"L_\": 10, \"DENSITY\": 0.001},\n",
153+
" {\"I_\": 100, \"J_\": 25, \"K_\": 100, \"L_\": 100, \"DENSITY\": 0.001},\n",
154+
" {\"I_\": 1000, \"J_\": 25, \"K_\": 100, \"L_\": 100, \"DENSITY\": 0.001},\n",
155+
" {\"I_\": 1000, \"J_\": 25, \"K_\": 1000, \"L_\": 100, \"DENSITY\": 0.001},\n",
156+
" {\"I_\": 1000, \"J_\": 25, \"K_\": 1000, \"L_\": 1000, \"DENSITY\": 0.001},\n",
157+
"]\n",
158+
"nonzeros = [10000, 100_000, 1_000_000, 10_000_000, 100_000_000, 1_000_000_000]\n",
159+
"\n",
160+
"if CI_MODE:\n",
161+
" configs = configs[:1]\n",
162+
" nonzeros = nonzeros[:1]\n",
163+
"\n",
164+
"finch_times = []\n",
165+
"numba_times = []\n",
166+
"\n",
167+
"for config in configs:\n",
168+
" B_sps = sparse.random((config[\"I_\"], config[\"K_\"], config[\"L_\"]), density=config[\"DENSITY\"], random_state=rng) * 10\n",
169+
" D_sps = rng.random((config[\"L_\"], config[\"J_\"])) * 10\n",
170+
" C_sps = rng.random((config[\"K_\"], config[\"J_\"])) * 10\n",
171+
"\n",
172+
" # ======= Finch =======\n",
173+
" os.environ[sparse._ENV_VAR_NAME] = \"Finch\"\n",
174+
" importlib.reload(sparse)\n",
175+
"\n",
176+
" B = sparse.asarray(B_sps.todense(), format=\"csf\")\n",
177+
" D = sparse.asarray(np.array(D_sps, order=\"F\"))\n",
178+
" C = sparse.asarray(np.array(C_sps, order=\"F\"))\n",
179+
"\n",
180+
" @sparse.compiled\n",
181+
" def mttkrp_finch(B, D, C):\n",
182+
" return sparse.sum(B[:, :, :, None] * D[None, None, :, :] * C[None, :, None, :], axis=(1, 2))\n",
183+
"\n",
184+
" # Compile\n",
185+
" result_finch = mttkrp_finch(B, D, C)\n",
186+
" # Benchmark\n",
187+
" time_finch = benchmark(mttkrp_finch, info=\"Finch\", args=[B, D, C])\n",
188+
"\n",
189+
" # ======= Numba =======\n",
190+
" os.environ[sparse._ENV_VAR_NAME] = \"Numba\"\n",
191+
" importlib.reload(sparse)\n",
192+
"\n",
193+
" B = sparse.asarray(B_sps, format=\"gcxs\")\n",
194+
" D = D_sps\n",
195+
" C = C_sps\n",
196+
"\n",
197+
" def mttkrp_numba(B, D, C):\n",
198+
" return sparse.sum(B[:, :, :, None] * D[None, None, :, :] * C[None, :, None, :], axis=(1, 2))\n",
199+
"\n",
200+
" # Compile\n",
201+
" result_numba = mttkrp_numba(B, D, C)\n",
202+
" # Benchmark\n",
203+
" time_numba = benchmark(mttkrp_numba, info=\"Numba\", args=[B, D, C])\n",
204+
"\n",
205+
" np.testing.assert_allclose(result_finch.todense(), result_numba.todense())\n",
206+
" finch_times.append(time_finch)\n",
207+
" numba_times.append(time_numba)"
208+
]
209+
},
210+
{
211+
"cell_type": "code",
212+
"execution_count": null,
213+
"metadata": {},
214+
"outputs": [],
215+
"source": [
216+
"fig, ax = plt.subplots(nrows=1, ncols=1)\n",
217+
"\n",
218+
"ax.plot(nonzeros, finch_times, \"o-\", label=\"Finch\")\n",
219+
"ax.plot(nonzeros, numba_times, \"o-\", label=\"Numba\")\n",
220+
"ax.grid(True)\n",
221+
"ax.set_xlabel(\"no. of elements\")\n",
222+
"ax.set_ylabel(\"time (sec)\")\n",
223+
"ax.set_title(\"MTTKRP\")\n",
224+
"ax.set_xscale(\"log\")\n",
225+
"ax.set_yscale(\"log\")\n",
226+
"ax.legend(loc=\"best\", numpoints=1)\n",
227+
"\n",
228+
"plt.show()"
229+
]
230+
},
231+
{
232+
"cell_type": "code",
233+
"execution_count": null,
234+
"metadata": {},
235+
"outputs": [],
236+
"source": [
237+
"print(\"SDDMM Example:\\n\")\n",
238+
"\n",
239+
"configs = [\n",
240+
" {\"LEN\": 10, \"DENSITY\": 0.1},\n",
241+
" {\"LEN\": 50, \"DENSITY\": 0.05},\n",
242+
" {\"LEN\": 100, \"DENSITY\": 0.01},\n",
243+
" {\"LEN\": 500, \"DENSITY\": 0.005},\n",
244+
" {\"LEN\": 1000, \"DENSITY\": 0.001},\n",
245+
" {\"LEN\": 5000, \"DENSITY\": 0.00005},\n",
246+
" {\"LEN\": 10000, \"DENSITY\": 0.00001},\n",
247+
"]\n",
248+
"size_n = [10, 50, 100, 500, 1000, 5000, 10000]\n",
249+
"\n",
250+
"if CI_MODE:\n",
251+
" configs = configs[:1]\n",
252+
" size_n = size_n[:1]\n",
253+
"\n",
254+
"finch_times = []\n",
255+
"numba_times = []\n",
256+
"scipy_times = []\n",
257+
"\n",
258+
"for config in configs:\n",
259+
" LEN = config[\"LEN\"]\n",
260+
" DENSITY = config[\"DENSITY\"]\n",
261+
"\n",
262+
" a_sps = rng.random((LEN, LEN)) * 10\n",
263+
" b_sps = rng.random((LEN, LEN)) * 10\n",
264+
" s_sps = sps.random(LEN, LEN, format=\"coo\", density=DENSITY, random_state=rng) * 10\n",
265+
" s_sps.sum_duplicates()\n",
266+
"\n",
267+
" # ======= Finch =======\n",
268+
" os.environ[sparse._ENV_VAR_NAME] = \"Finch\"\n",
269+
" importlib.reload(sparse)\n",
270+
"\n",
271+
" s = sparse.asarray(s_sps)\n",
272+
" a = sparse.asarray(np.array(a_sps, order=\"F\"))\n",
273+
" b = sparse.asarray(np.array(b_sps, order=\"C\"))\n",
274+
"\n",
275+
" @sparse.compiled\n",
276+
" def sddmm_finch(s, a, b):\n",
277+
" return sparse.sum(\n",
278+
" s[:, :, None] * (a[:, None, :] * sparse.permute_dims(b, (1, 0))[None, :, :]),\n",
279+
" axis=-1,\n",
280+
" )\n",
281+
"\n",
282+
" # Compile\n",
283+
" result_finch = sddmm_finch(s, a, b)\n",
284+
" # Benchmark\n",
285+
" time_finch = benchmark(sddmm_finch, info=\"Finch\", args=[s, a, b])\n",
286+
"\n",
287+
" # ======= Numba =======\n",
288+
" os.environ[sparse._ENV_VAR_NAME] = \"Numba\"\n",
289+
" importlib.reload(sparse)\n",
290+
"\n",
291+
" s = sparse.asarray(s_sps)\n",
292+
" a = a_sps\n",
293+
" b = b_sps\n",
294+
"\n",
295+
" def sddmm_numba(s, a, b):\n",
296+
" return s * (a @ b)\n",
297+
"\n",
298+
" # Compile\n",
299+
" result_numba = sddmm_numba(s, a, b)\n",
300+
" # Benchmark\n",
301+
" time_numba = benchmark(sddmm_numba, info=\"Numba\", args=[s, a, b])\n",
302+
"\n",
303+
" # ======= SciPy =======\n",
304+
" def sddmm_scipy(s, a, b):\n",
305+
" return s.multiply(a @ b)\n",
306+
"\n",
307+
" s = s_sps.asformat(\"csr\")\n",
308+
" a = a_sps\n",
309+
" b = b_sps\n",
310+
"\n",
311+
" result_scipy = sddmm_scipy(s, a, b)\n",
312+
" # Benchmark\n",
313+
" time_scipy = benchmark(sddmm_scipy, info=\"SciPy\", args=[s, a, b])\n",
314+
"\n",
315+
" finch_times.append(time_finch)\n",
316+
" numba_times.append(time_numba)\n",
317+
" scipy_times.append(time_scipy)"
318+
]
319+
},
320+
{
321+
"cell_type": "code",
322+
"execution_count": null,
323+
"metadata": {},
324+
"outputs": [],
325+
"source": [
326+
"fig, ax = plt.subplots(nrows=1, ncols=1)\n",
327+
"\n",
328+
"ax.plot(size_n, finch_times, \"o-\", label=\"Finch\")\n",
329+
"ax.plot(size_n, numba_times, \"o-\", label=\"Numba\")\n",
330+
"ax.plot(size_n, scipy_times, \"o-\", label=\"SciPy\")\n",
331+
"\n",
332+
"ax.grid(True)\n",
333+
"ax.set_xlabel(\"size N\")\n",
334+
"ax.set_ylabel(\"time (sec)\")\n",
335+
"ax.set_title(\"SDDMM\")\n",
336+
"ax.set_xscale(\"log\")\n",
337+
"# ax.set_yscale('log')\n",
338+
"ax.legend(loc=\"best\", numpoints=1)\n",
339+
"\n",
340+
"plt.show()"
341+
]
342+
}
343+
],
344+
"metadata": {
345+
"kernelspec": {
346+
"display_name": "sparse-dev",
347+
"language": "python",
348+
"name": "python3"
349+
},
350+
"language_info": {
351+
"codemirror_mode": {
352+
"name": "ipython",
353+
"version": 3
354+
},
355+
"file_extension": ".py",
356+
"mimetype": "text/x-python",
357+
"name": "python",
358+
"nbconvert_exporter": "python",
359+
"pygments_lexer": "ipython3",
360+
"version": "3.12.2"
361+
}
362+
},
363+
"nbformat": 4,
364+
"nbformat_minor": 2
365+
}

docs/generated/sparse.COO.T.rst

-6
This file was deleted.

docs/generated/sparse.COO.all.rst

-6
This file was deleted.

0 commit comments

Comments
 (0)