/ concept-collection / math-webgpu-sandbox
Sign in
concept-collection / math-webgpu-sandbox
math-webgpu-sandbox / index.html
198 lines · 8.5 KBCodeBlameHistory
2<html lang="en">
3 <head>
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1" />
6 <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><rect x=%225%22 y=%225%22 width=%2290%22 height=%2290%22 rx=%2216%22 fill=%22%230969da%22/><text x=%2250%22 y=%2268%22 font-size=%2252%22 text-anchor=%22middle%22 fill=%22white%22 font-family=%22monospace%22 font-weight=%22bold%22>⚡</text></svg>" />
7 <title>math-webgpu-sandbox — MATLAB-syntax scripts on WebGPU</title>
8 <style>
9 :root {
10 --bg: #ffffff;
11 --ink: #1f2328;
12 --ink-2: #57606a;
13 --line: #d0d7de;
14 --accent: #0969da;
15 --pane-bg: #f4f6f8;
16 --tok-com: #6e7781;
17 --tok-str: #0a3069;
18 --tok-num: #0550ae;
19 --tok-kw: #cf222e;
20 --tok-ext: #8250df;
21 --warn-bg: #fff8e5;
22 --warn-line: #e3c37a;
23 --warn-edge: #bf8700;
24 --err: #b35900;
25 color-scheme: light dark;
26 }
27 @media (prefers-color-scheme: dark) {
28 :root {
29 --bg: #14171a;
30 --ink: #e6e9ec;
31 --ink-2: #9aa4af;
32 --line: #333b44;
33 --accent: #58a6ff;
34 --pane-bg: #191d22;
35 --tok-com: #8b949e;
36 --tok-str: #a5d6ff;
37 --tok-num: #79c0ff;
38 --tok-kw: #ff7b72;
39 --tok-ext: #d2a8ff;
40 --warn-bg: #2b2410;
41 --warn-line: #6b5518;
42 --warn-edge: #e3b341;
43 --err: #f0883e;
44 }
45 }
46 body {
47 margin: 0;
48 background: var(--bg);
49 color: var(--ink);
50 font: 15px/1.5 system-ui, -apple-system, sans-serif;
51 }
52 main { max-width: 1200px; margin: 0 auto; padding: 20px 16px 48px; }
53 h1 { font-size: 20px; margin: 0 0 2px; }
54 .sub { color: var(--ink-2); margin: 0 0 10px; font-size: 13px; }
55 .sub a { color: var(--accent); }
56 .warn {
57 margin: 0 0 12px; padding: 10px 14px;
58 border: 1px solid var(--warn-line); border-left: 5px solid var(--warn-edge);
59 border-radius: 6px; background: var(--warn-bg);
60 font-size: 13.5px; line-height: 1.5;
61 }
62 .controls {
63 display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center;
64 padding: 6px 0;
65 }
66 .controls label { color: var(--ink-2); font-size: 13px; white-space: nowrap; }
67 select, button {
68 font: inherit; font-size: 13px;
69 color: var(--ink); background: var(--bg);
70 border: 1px solid var(--line); border-radius: 6px;
71 padding: 4px 10px;
72 }
73 button { cursor: pointer; }
74 button:hover:not(:disabled) { border-color: var(--accent); }
75 button:disabled { opacity: 0.5; cursor: default; }
76 button.primary { border-color: var(--accent); color: var(--accent); font-weight: 600; }
77 #device { font-size: 12.5px; color: var(--ink-2); margin-left: auto; }
78 .split { display: flex; gap: 14px; margin-top: 10px; align-items: stretch; }
79 .box {
80 border: 1px solid var(--line); border-radius: 8px; overflow: hidden;
81 display: flex; flex-direction: column; min-width: 0;
82 }
83 #editorbox { flex: 1 1 56%; }
84 #outbox { flex: 1 1 44%; }
85 .box-head {
86 display: flex; gap: 10px; align-items: center; justify-content: space-between;
87 padding: 6px 10px; font-size: 12px; color: var(--ink-2);
88 background: var(--pane-bg); border-bottom: 1px solid var(--line);
89 }
90 .editor-code { position: relative; flex: 1; min-height: 30em; }
91 .editor-code > pre,
92 .editor-code > textarea {
93 margin: 0; padding: 10px 12px; border: 0;
94 box-sizing: border-box; width: 100%; height: 100%;
95 font: 12.5px/1.6 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
96 tab-size: 2;
97 white-space: pre; overflow-wrap: normal;
98 }
99 #highlight {
100 position: absolute; inset: 0; overflow: hidden;
101 pointer-events: none; background: var(--bg); color: var(--ink);
102 }
103 #source {
104 position: relative; z-index: 1; display: block;
105 resize: none; overflow: auto;
106 background: transparent; color: transparent; caret-color: var(--ink);
107 }
108 #source:focus { outline: none; }
109 #source::selection { background: color-mix(in srgb, var(--accent) 28%, transparent); }
110 .console {
111 flex: 1; margin: 0; padding: 10px 12px; overflow: auto;
112 font: 12.5px/1.6 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
113 white-space: pre-wrap; background: var(--pane-bg);
114 min-height: 8em;
115 }
116 .console .err { color: var(--err); }
117 .console .meta { color: var(--ink-2); }
118 #cpuconsole { border-top: 1px solid var(--line); max-height: 14em; display: none; }
119 #timings {
120 margin-top: 12px; font-size: 13.5px; font-variant-numeric: tabular-nums;
121 border-collapse: collapse; display: none;
122 }
123 #timings td, #timings th {
124 border: 1px solid var(--line); padding: 4px 12px; text-align: right;
125 }
126 #timings th { background: var(--pane-bg); font-weight: 600; }
127 #timings td:first-child, #timings th:first-child { text-align: left; }
128 details { margin-top: 12px; font-size: 13px; }
129 details pre {
130 margin: 6px 0 0; padding: 8px 10px; overflow: auto;
131 background: var(--pane-bg); border: 1px solid var(--line); border-radius: 6px;
132 font: 12px/1.6 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
133 }
134 #blurb { margin-top: 14px; font-size: 13px; color: var(--ink-2); max-width: 72em; }
135 #blurb code { font-size: 12px; }
136 .tok-com { color: var(--tok-com); }
137 .tok-str { color: var(--tok-str); }
138 .tok-num { color: var(--tok-num); }
139 .tok-kw { color: var(--tok-kw); font-weight: 600; }
140 .tok-ext { color: var(--tok-ext); }
141 @media (max-width: 900px) {
142 .split { flex-direction: column; }
143 .editor-code { min-height: 22em; }
144 }
145 </style>
146 </head>
147 <body>
148 <main>
149 <h1>math-webgpu-sandbox</h1>
150 <p class="sub">
151 MATLAB-syntax scripts compiled to fused WebGPU compute kernels — time them with
152 <code>tic</code>/<code>toc</code>, then paste the same script into MATLAB and compare.
153 <a href="https://github.com/concept-collection/math-webgpu-sandbox">source</a>
154 </p>
155 <div id="gpuwarn" class="warn" hidden></div>
156 <div class="controls">
157 <label>example
158 <select id="example"></select>
159 </label>
160 <button id="run" class="primary">Run on GPU</button>
161 <button id="runcpu" title="Run the same script through numbl's CPU engine in a worker">Run on CPU (numbl)</button>
162 <button id="copy" title="Copy the script for pasting into MATLAB">Copy script</button>
163 <span id="device"></span>
164 </div>
165 <div class="split">
166 <div class="box" id="editorbox">
167 <div class="box-head"><span>script.m — valid MATLAB</span><span id="editstate"></span></div>
168 <div class="editor-code">
169 <pre id="highlight" aria-hidden="true"></pre>
170 <textarea id="source" spellcheck="false" autocomplete="off"></textarea>
171 </div>
172 </div>
173 <div class="box" id="outbox">
174 <div class="box-head"><span>output</span><span id="runstate"></span></div>
175 <pre id="console" class="console"></pre>
176 <pre id="cpuconsole" class="console"></pre>
177 </div>
178 </div>
179 <table id="timings"></table>
180 <details id="plandetails" hidden>
181 <summary>compiled GPU plan</summary>
182 <pre id="plan"></pre>
183 </details>
184 <p id="blurb">
185 The GPU computes in <b>f32</b> (WebGPU has no f64) while MATLAB defaults to double —
186 timings compare fairly, values agree to single precision. For the closest MATLAB
187 comparison use <code>single</code> arrays. <code>rand</code> here is a deterministic
188 counter-based generator: statistics match MATLAB's, individual draws do not.
189 Supported: elementwise math (fused per source line, including comparisons and
190 logicals), <code>A*B</code>, transpose, <code>sum/mean/prod/max/min/norm/dot</code>,
191 <code>A(:)</code>/<code>reshape</code> (free), <code>for</code> loops (replayed, not
192 unrolled), <code>tic/toc/disp/fprintf</code>. Not (yet) supported: indexing/slicing
193 beyond <code>(:)</code>, <code>if/while</code>, complex numbers, user functions.
194 </p>
195 </main>
196 <script type="module" src="/src/main.ts"></script>
197 </body>
198</html>
moveopenescclose