oidn-web 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +83 -19
  3. package/dist/oidn.js +3239 -2642
  4. package/dist/oidn.umd.cjs +512 -296
  5. package/lib/UNet.d.ts +54 -20
  6. package/lib/UNet.js +194 -118
  7. package/lib/UNet.js.map +1 -1
  8. package/lib/backend.d.ts +1 -8
  9. package/lib/backend.js +1 -9
  10. package/lib/backend.js.map +1 -1
  11. package/lib/finalRgbShader.d.ts +13 -0
  12. package/lib/finalRgbShader.js +160 -0
  13. package/lib/finalRgbShader.js.map +1 -0
  14. package/lib/graphOptimizer.js +1 -2
  15. package/lib/graphOptimizer.js.map +1 -1
  16. package/lib/hdrTransfer.d.ts +14 -0
  17. package/lib/hdrTransfer.js +61 -0
  18. package/lib/hdrTransfer.js.map +1 -0
  19. package/lib/main.d.ts +16 -7
  20. package/lib/main.js +4 -5
  21. package/lib/main.js.map +1 -1
  22. package/lib/nativeUNet.d.ts +39 -3
  23. package/lib/nativeUNet.js +449 -120
  24. package/lib/nativeUNet.js.map +1 -1
  25. package/lib/process.d.ts +5 -11
  26. package/lib/process.js +35 -49
  27. package/lib/process.js.map +1 -1
  28. package/lib/tileScheduler.d.ts +32 -4
  29. package/lib/tileScheduler.js +133 -20
  30. package/lib/tileScheduler.js.map +1 -1
  31. package/package.json +9 -2
  32. package/src/UNet.ts +287 -158
  33. package/src/backend.ts +1 -14
  34. package/src/finalRgbShader.ts +186 -0
  35. package/src/graphOptimizer.ts +1 -2
  36. package/src/hdrTransfer.ts +88 -0
  37. package/src/main.ts +28 -13
  38. package/src/nativeUNet.ts +515 -116
  39. package/src/process.ts +43 -70
  40. package/src/tileScheduler.ts +216 -24
  41. package/benchmarks/compare.mjs +0 -651
  42. package/benchmarks/leak.mjs +0 -255
  43. package/benchmarks/results/before-spatial.json +0 -391
  44. package/benchmarks/results/before-spatial.md +0 -47
  45. package/benchmarks/results/int8-scan.json +0 -2007
  46. package/benchmarks/results/int8-scan.md +0 -160
  47. package/benchmarks/results/int8-w8a8-scan.json +0 -2007
  48. package/benchmarks/results/int8-w8a8-scan.md +0 -160
  49. package/benchmarks/results/int8-weight-channel.json +0 -1413
  50. package/benchmarks/results/int8-weight-channel.md +0 -118
  51. package/benchmarks/results/int8-weight-only.json +0 -1437
  52. package/benchmarks/results/int8-weight-only.md +0 -118
  53. package/benchmarks/results/kernel-webnn-final.json +0 -1115
  54. package/benchmarks/results/kernel-webnn-final.md +0 -104
  55. package/benchmarks/results/latest-optimized.json +0 -375
  56. package/benchmarks/results/latest-optimized.md +0 -47
  57. package/benchmarks/results/latest.json +0 -391
  58. package/benchmarks/results/latest.md +0 -47
  59. package/benchmarks/results/profile-baseline.json +0 -331
  60. package/benchmarks/results/profile-baseline.md +0 -12
  61. package/benchmarks/results/profile-conv2x.json +0 -331
  62. package/benchmarks/results/profile-conv2x.md +0 -12
  63. package/benchmarks/results/profile-fast-init.json +0 -385
  64. package/benchmarks/results/profile-fast-init.md +0 -47
  65. package/benchmarks/results/profile-fp16-fma.json +0 -369
  66. package/benchmarks/results/profile-fp16-fma.md +0 -47
  67. package/benchmarks/results/profile-fp16-tiled-decoder.json +0 -369
  68. package/benchmarks/results/profile-fp16-tiled-decoder.md +0 -47
  69. package/benchmarks/results/profile-fp16-tiled-encoder.json +0 -369
  70. package/benchmarks/results/profile-fp16-tiled-encoder.md +0 -47
  71. package/benchmarks/results/profile-fp16-unfused-pool.json +0 -385
  72. package/benchmarks/results/profile-fp16-unfused-pool.md +0 -47
  73. package/benchmarks/results/profile-input-major.json +0 -347
  74. package/benchmarks/results/profile-input-major.md +0 -12
  75. package/benchmarks/results/profile-k16.json +0 -347
  76. package/benchmarks/results/profile-k16.md +0 -12
  77. package/benchmarks/results/profile-k4.json +0 -347
  78. package/benchmarks/results/profile-k4.md +0 -12
  79. package/benchmarks/results/profile-pool-reuse.json +0 -331
  80. package/benchmarks/results/profile-pool-reuse.md +0 -12
  81. package/benchmarks/results/profile-precompiled.json +0 -385
  82. package/benchmarks/results/profile-precompiled.md +0 -47
  83. package/benchmarks/results/profile-static-channels.json +0 -385
  84. package/benchmarks/results/profile-static-channels.md +0 -47
  85. package/benchmarks/results/profile-static-io.json +0 -385
  86. package/benchmarks/results/profile-static-io.md +0 -47
  87. package/benchmarks/results/profile-tiled-conv.json +0 -331
  88. package/benchmarks/results/profile-tiled-conv.md +0 -12
  89. package/benchmarks/results/profile-tiled-decoder.json +0 -347
  90. package/benchmarks/results/profile-tiled-decoder.md +0 -12
  91. package/benchmarks/results/profile-tiled-matmul.json +0 -331
  92. package/benchmarks/results/profile-tiled-matmul.md +0 -12
  93. package/benchmarks/results/profile-unfused-decoder.json +0 -379
  94. package/benchmarks/results/profile-unfused-decoder.md +0 -12
  95. package/benchmarks/results/profile-unfused-pool.json +0 -347
  96. package/benchmarks/results/profile-unfused-pool.md +0 -12
  97. package/benchmarks/results/spatial-auto.json +0 -575
  98. package/benchmarks/results/spatial-auto.md +0 -61
  99. package/benchmarks/results/subgroup-smoke.json +0 -1094
  100. package/benchmarks/results/subgroup-smoke.md +0 -104
  101. package/benchmarks/results/webnn-smoke.json +0 -739
  102. package/benchmarks/results/webnn-smoke.md +0 -76
  103. package/scripts/inspect-model.mjs +0 -64
  104. package/tests/modelSpec.test.mjs +0 -128
  105. package/tests/resourceLifecycle.test.mjs +0 -383
  106. package/tests/tileScheduler.test.mjs +0 -90
@@ -1,255 +0,0 @@
1
- #!/usr/bin/env node
2
- import { createServer } from 'node:http';
3
- import { existsSync } from 'node:fs';
4
- import { readFile } from 'node:fs/promises';
5
- import path from 'node:path';
6
- import process from 'node:process';
7
- import { fileURLToPath } from 'node:url';
8
- import { chromium } from 'playwright-core';
9
-
10
- const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
11
-
12
- function options(argv) {
13
- const result = { cycles: 6, engine: 'wgsl' };
14
- for (let index = 0; index < argv.length; index += 2) {
15
- const name = argv[index];
16
- const value = argv[index + 1];
17
- if (name === '--cycles') result.cycles = Number(value);
18
- else if (name === '--engine') result.engine = value;
19
- else if (name === '--chrome') result.chrome = value;
20
- else throw new Error(`Unknown option ${name}`);
21
- }
22
- if (!Number.isInteger(result.cycles) || result.cycles < 2) {
23
- throw new Error('--cycles must be an integer of at least 2');
24
- }
25
- if (!['wgsl', 'webnn'].includes(result.engine)) {
26
- throw new Error('--engine must be wgsl or webnn');
27
- }
28
- return result;
29
- }
30
-
31
- function defaultChrome() {
32
- return [
33
- process.env.CHROME_PATH,
34
- '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
35
- '/Applications/Chromium.app/Contents/MacOS/Chromium',
36
- '/usr/bin/google-chrome',
37
- '/usr/bin/chromium'
38
- ].find((candidate) => candidate && existsSync(candidate));
39
- }
40
-
41
- async function server() {
42
- const files = new Map([
43
- ['/oidn.js', path.join(root, 'dist/oidn.js')],
44
- ['/model.tza', path.join(root, 'weights/rt_hdr.tza')]
45
- ]);
46
- const instance = createServer(async (request, response) => {
47
- const pathname = new URL(request.url, 'http://127.0.0.1').pathname;
48
- if (pathname === '/') {
49
- response.writeHead(200, { 'content-type': 'text/html' });
50
- response.end(
51
- '<!doctype html><meta charset="utf-8"><title>OIDN resource stress</title>'
52
- );
53
- return;
54
- }
55
- if (pathname === '/favicon.ico') {
56
- response.writeHead(204).end();
57
- return;
58
- }
59
- const file = files.get(pathname);
60
- if (!file) {
61
- response.writeHead(404).end();
62
- return;
63
- }
64
- response.writeHead(200, {
65
- 'content-type': pathname.endsWith('.js')
66
- ? 'text/javascript'
67
- : 'application/octet-stream',
68
- 'cache-control': 'no-store'
69
- });
70
- response.end(await readFile(file));
71
- });
72
- await new Promise((resolve, reject) => {
73
- instance.once('error', reject);
74
- instance.listen(0, '127.0.0.1', resolve);
75
- });
76
- return {
77
- origin: `http://127.0.0.1:${instance.address().port}`,
78
- close: () =>
79
- new Promise((resolve, reject) =>
80
- instance.close((error) => (error ? reject(error) : resolve()))
81
- )
82
- };
83
- }
84
-
85
- async function main() {
86
- const config = options(process.argv.slice(2));
87
- const chrome = config.chrome || defaultChrome();
88
- if (!chrome) throw new Error('Chrome not found; pass --chrome <path>');
89
-
90
- const { spawn } = await import('node:child_process');
91
- await new Promise((resolve, reject) => {
92
- const child = spawn('npm', ['run', 'build'], {
93
- cwd: root,
94
- stdio: 'inherit'
95
- });
96
- child.once('error', reject);
97
- child.once('exit', (code) =>
98
- code === 0
99
- ? resolve()
100
- : reject(new Error(`OIDN build exited with ${code}`))
101
- );
102
- });
103
-
104
- const host = await server();
105
- let browser;
106
- try {
107
- browser = await chromium.launch({
108
- executablePath: chrome,
109
- headless: true,
110
- args: [
111
- '--enable-unsafe-webgpu',
112
- '--enable-precise-memory-info',
113
- '--js-flags=--expose-gc',
114
- '--enable-features=Vulkan,UseSkiaRenderer,WebMachineLearningNeuralNetwork'
115
- ]
116
- });
117
- const page = await browser.newPage();
118
- const browserErrors = [];
119
- page.on('pageerror', (error) => browserErrors.push(error.message));
120
- page.on('console', (message) => {
121
- if (message.type() === 'error') browserErrors.push(message.text());
122
- });
123
- await page.goto(host.origin);
124
- const result = await page.evaluate(
125
- async ({ cycles, engine, origin }) => {
126
- if (!navigator.gpu) throw new Error('WebGPU is unavailable');
127
- if (engine === 'webnn' && !navigator.ml) {
128
- throw new Error('WebNN is unavailable in this Chrome configuration');
129
- }
130
- const module = await import(`${origin}/oidn.js`);
131
- const model = await fetch(`${origin}/model.tza`).then((response) =>
132
- response.arrayBuffer()
133
- );
134
- const adapter = await navigator.gpu.requestAdapter({
135
- powerPreference: 'high-performance'
136
- });
137
- if (!adapter) throw new Error('No WebGPU adapter');
138
- const requiredFeatures = adapter.features.has('shader-f16')
139
- ? ['shader-f16']
140
- : [];
141
- const device = await adapter.requestDevice({ requiredFeatures });
142
- const adapterInfo = adapter.info ?? {};
143
- const shapes = [
144
- { width: 32, height: 32 },
145
- { width: 48, height: 48 },
146
- { width: 80, height: 64 }
147
- ];
148
- const heap = [];
149
- const resources = [];
150
-
151
- for (let cycle = 0; cycle < cycles; cycle++) {
152
- device.pushErrorScope('validation');
153
- const unet = await module.initUNetFromBuffer(
154
- model.slice(0),
155
- { device, adapterInfo },
156
- {
157
- aux: false,
158
- hdr: true,
159
- engine,
160
- precision: requiredFeatures.length ? 'fp16' : 'fp32',
161
- maxTileSize: 128,
162
- dynamicTile: false
163
- }
164
- );
165
- for (const shape of shapes) {
166
- const values = new Float32Array(shape.width * shape.height * 4);
167
- values.fill(0.25 + cycle * 0.001);
168
- const input = device.createBuffer({
169
- size: values.byteLength,
170
- usage:
171
- GPUBufferUsage.STORAGE |
172
- GPUBufferUsage.COPY_SRC |
173
- GPUBufferUsage.COPY_DST,
174
- mappedAtCreation: true
175
- });
176
- new Float32Array(input.getMappedRange()).set(values);
177
- input.unmap();
178
- await new Promise((resolve, reject) => {
179
- try {
180
- unet.tileExecute({
181
- color: { data: input, ...shape },
182
- done: resolve
183
- });
184
- } catch (error) {
185
- reject(error);
186
- }
187
- });
188
- await device.queue.onSubmittedWorkDone();
189
- input.destroy();
190
- }
191
- const beforeDispose = unet.getRuntimeInfo().resources;
192
- unet.dispose();
193
- await device.queue.onSubmittedWorkDone();
194
- const afterDispose = unet.getRuntimeInfo().resources;
195
- const validationError = await device.popErrorScope();
196
- if (validationError) throw new Error(validationError.message);
197
- if (
198
- afterDispose.live !== 0 ||
199
- afterDispose.pending !== 0 ||
200
- afterDispose.created !== afterDispose.destroyed
201
- ) {
202
- throw new Error(
203
- `cycle ${cycle}: resources did not return to zero: ` +
204
- JSON.stringify(afterDispose)
205
- );
206
- }
207
- resources.push({ beforeDispose, afterDispose });
208
- globalThis.gc?.();
209
- heap.push(performance.memory?.usedJSHeapSize ?? null);
210
- }
211
- device.destroy();
212
- return { heap, resources, adapter: adapterInfo };
213
- },
214
- { ...config, origin: host.origin }
215
- );
216
-
217
- if (browserErrors.length) {
218
- throw new Error(`Browser errors:\n${browserErrors.join('\n')}`);
219
- }
220
- const measuredHeap = result.heap.filter(Number.isFinite).slice(2);
221
- const retainedHeapBytes =
222
- measuredHeap.length > 1
223
- ? measuredHeap.at(-1) - Math.min(...measuredHeap)
224
- : null;
225
- if (retainedHeapBytes !== null && retainedHeapBytes > 32 * 1024 * 1024) {
226
- throw new Error(
227
- `JS heap retained ${(retainedHeapBytes / 1024 / 1024).toFixed(1)} MiB`
228
- );
229
- }
230
- console.log(
231
- JSON.stringify(
232
- {
233
- status: 'passed',
234
- engine: config.engine,
235
- cycles: config.cycles,
236
- retainedHeapBytes,
237
- peakOwnedResources: Math.max(
238
- ...result.resources.map((entry) => entry.beforeDispose.peakLive)
239
- ),
240
- adapter: result.adapter
241
- },
242
- null,
243
- 2
244
- )
245
- );
246
- } finally {
247
- await browser?.close();
248
- await host.close();
249
- }
250
- }
251
-
252
- main().catch((error) => {
253
- console.error(error instanceof Error ? error.stack : error);
254
- process.exitCode = 1;
255
- });
@@ -1,391 +0,0 @@
1
- {
2
- "generatedAt": "2026-08-20T04:41:13.388Z",
3
- "currentCommit": "e6b8577b1c69cc8ce979022717984aec5b9ea881",
4
- "baselineCommit": "136c00c34aa5cf4561b4137034dbd643177f0a5f",
5
- "settings": {
6
- "width": 512,
7
- "height": 512,
8
- "tileSize": 512,
9
- "warmup": 2,
10
- "runs": 5,
11
- "model": "rt_hdr_calb_cnrm_large.tza",
12
- "gpuQueueCompletionIncluded": true
13
- },
14
- "browser": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
15
- "adapter": {
16
- "vendor": "apple",
17
- "architecture": "metal-3",
18
- "device": "",
19
- "description": ""
20
- },
21
- "results": [
22
- {
23
- "label": "TFJS (136c00c)",
24
- "bundle": "baseline",
25
- "baseline": true,
26
- "initializationMs": 8.5,
27
- "timesMs": [
28
- 37.29999999701977,
29
- 37.100000001490116,
30
- 37.5,
31
- 36.899999998509884,
32
- 37.399999998509884
33
- ],
34
- "supportsFP16": true,
35
- "adapter": {
36
- "vendor": "apple",
37
- "architecture": "metal-3",
38
- "device": "",
39
- "description": ""
40
- },
41
- "summary": {
42
- "minMs": 36.899999998509884,
43
- "medianMs": 37.29999999701977,
44
- "meanMs": 37.23999999910593,
45
- "p95Ms": 37.5,
46
- "maxMs": 37.5
47
- },
48
- "messages": []
49
- },
50
- {
51
- "label": "WGSL FP32",
52
- "bundle": "current",
53
- "baseline": false,
54
- "precision": "fp32",
55
- "initializationMs": 39.399999998509884,
56
- "timesMs": [
57
- 38.19999999552965,
58
- 38.100000001490116,
59
- 37.79999999701977,
60
- 38.20000000298023,
61
- 38.100000001490116
62
- ],
63
- "executionProfile": {
64
- "totalMs": 36.714113,
65
- "layers": [
66
- {
67
- "id": "input-pack",
68
- "durationMs": 0.051164
69
- },
70
- {
71
- "id": "enc_conv1a",
72
- "durationMs": 0.840212
73
- },
74
- {
75
- "id": "enc_conv1b",
76
- "durationMs": 3.694748
77
- },
78
- {
79
- "id": "pool1",
80
- "durationMs": 0.413064
81
- },
82
- {
83
- "id": "enc_conv2a",
84
- "durationMs": 1.403019
85
- },
86
- {
87
- "id": "enc_conv2b",
88
- "durationMs": 2.701085
89
- },
90
- {
91
- "id": "pool2",
92
- "durationMs": 0.072955
93
- },
94
- {
95
- "id": "enc_conv3a",
96
- "durationMs": 0.770299
97
- },
98
- {
99
- "id": "enc_conv3b",
100
- "durationMs": 0.98883
101
- },
102
- {
103
- "id": "pool3",
104
- "durationMs": 0.017833
105
- },
106
- {
107
- "id": "enc_conv4a",
108
- "durationMs": 0.399939
109
- },
110
- {
111
- "id": "enc_conv4b",
112
- "durationMs": 0.609888
113
- },
114
- {
115
- "id": "pool4",
116
- "durationMs": 0.008625
117
- },
118
- {
119
- "id": "enc_conv5a",
120
- "durationMs": 0.25828
121
- },
122
- {
123
- "id": "enc_conv5b",
124
- "durationMs": 0.336652
125
- },
126
- {
127
- "id": "dec_conv4a",
128
- "durationMs": 1.243235
129
- },
130
- {
131
- "id": "dec_conv4b",
132
- "durationMs": 0.670344
133
- },
134
- {
135
- "id": "dec_conv3a",
136
- "durationMs": 2.621255
137
- },
138
- {
139
- "id": "dec_conv3b",
140
- "durationMs": 0.990622
141
- },
142
- {
143
- "id": "dec_conv2a",
144
- "durationMs": 4.373216
145
- },
146
- {
147
- "id": "dec_conv2b",
148
- "durationMs": 2.320394
149
- },
150
- {
151
- "id": "dec_conv1a",
152
- "durationMs": 7.416744
153
- },
154
- {
155
- "id": "dec_conv1b",
156
- "durationMs": 4.014733
157
- },
158
- {
159
- "id": "dec_conv1c",
160
- "durationMs": 0.496977
161
- }
162
- ]
163
- },
164
- "runtimeInfo": {
165
- "configuredEngine": "wgsl",
166
- "gpuEngine": "wgsl",
167
- "precision": "fp32",
168
- "model": "oidn-unet-large-v1",
169
- "modelFamily": "oidn-unet-large",
170
- "inputChannels": 9,
171
- "dynamicTile": {
172
- "enabled": false,
173
- "currentTileSize": 512,
174
- "minTileSize": 256,
175
- "maxTileSize": 512,
176
- "targetTileTimeMs": 16
177
- },
178
- "lastExecution": {
179
- "width": 512,
180
- "height": 512,
181
- "tileWidth": 512,
182
- "tileHeight": 512,
183
- "tileCount": 1,
184
- "durationMs": 38.5,
185
- "tileTimeMs": {
186
- "min": 38.5,
187
- "median": 38.5,
188
- "mean": 38.5,
189
- "max": 38.5
190
- }
191
- }
192
- },
193
- "supportsFP16": true,
194
- "adapter": {
195
- "vendor": "apple",
196
- "architecture": "metal-3",
197
- "device": "",
198
- "description": ""
199
- },
200
- "summary": {
201
- "minMs": 37.79999999701977,
202
- "medianMs": 38.100000001490116,
203
- "meanMs": 38.079999999701975,
204
- "p95Ms": 38.20000000298023,
205
- "maxMs": 38.20000000298023
206
- },
207
- "messages": [],
208
- "validation": {
209
- "sampleCount": 6144,
210
- "meanAbsoluteError": 0.0000011096847932397698,
211
- "rootMeanSquaredError": 0.0000018071588418628667,
212
- "maxAbsoluteError": 0.000013589859008789062,
213
- "passed": true,
214
- "thresholds": {
215
- "maxMeanError": 0.0001,
216
- "maxAbsoluteError": 0.001
217
- }
218
- }
219
- },
220
- {
221
- "label": "WGSL FP16",
222
- "bundle": "current",
223
- "baseline": false,
224
- "precision": "fp16",
225
- "initializationMs": 31.399999998509884,
226
- "timesMs": [
227
- 30.399999998509884,
228
- 29.399999998509884,
229
- 30.30000000447035,
230
- 29.600000001490116,
231
- 30.399999998509884
232
- ],
233
- "executionProfile": {
234
- "totalMs": 29.073979,
235
- "layers": [
236
- {
237
- "id": "input-pack",
238
- "durationMs": 0.044457
239
- },
240
- {
241
- "id": "enc_conv1a",
242
- "durationMs": 0.617963
243
- },
244
- {
245
- "id": "enc_conv1b",
246
- "durationMs": 3.851724
247
- },
248
- {
249
- "id": "pool1",
250
- "durationMs": 0.355894
251
- },
252
- {
253
- "id": "enc_conv2a",
254
- "durationMs": 1.278839
255
- },
256
- {
257
- "id": "enc_conv2b",
258
- "durationMs": 1.971796
259
- },
260
- {
261
- "id": "pool2",
262
- "durationMs": 0.049789
263
- },
264
- {
265
- "id": "enc_conv3a",
266
- "durationMs": 0.680792
267
- },
268
- {
269
- "id": "enc_conv3b",
270
- "durationMs": 0.844449
271
- },
272
- {
273
- "id": "pool3",
274
- "durationMs": 0.146366
275
- },
276
- {
277
- "id": "enc_conv4a",
278
- "durationMs": 0.782577
279
- },
280
- {
281
- "id": "enc_conv4b",
282
- "durationMs": 0.628628
283
- },
284
- {
285
- "id": "pool4",
286
- "durationMs": 0.01
287
- },
288
- {
289
- "id": "enc_conv5a",
290
- "durationMs": 0.184988
291
- },
292
- {
293
- "id": "enc_conv5b",
294
- "durationMs": 0.237694
295
- },
296
- {
297
- "id": "dec_conv4a",
298
- "durationMs": 0.961274
299
- },
300
- {
301
- "id": "dec_conv4b",
302
- "durationMs": 0.539551
303
- },
304
- {
305
- "id": "dec_conv3a",
306
- "durationMs": 1.739311
307
- },
308
- {
309
- "id": "dec_conv3b",
310
- "durationMs": 0.836199
311
- },
312
- {
313
- "id": "dec_conv2a",
314
- "durationMs": 3.206554
315
- },
316
- {
317
- "id": "dec_conv2b",
318
- "durationMs": 2.382521
319
- },
320
- {
321
- "id": "dec_conv1a",
322
- "durationMs": 4.440979
323
- },
324
- {
325
- "id": "dec_conv1b",
326
- "durationMs": 3.088521
327
- },
328
- {
329
- "id": "dec_conv1c",
330
- "durationMs": 0.193113
331
- }
332
- ]
333
- },
334
- "runtimeInfo": {
335
- "configuredEngine": "wgsl",
336
- "gpuEngine": "wgsl",
337
- "precision": "fp16",
338
- "model": "oidn-unet-large-v1",
339
- "modelFamily": "oidn-unet-large",
340
- "inputChannels": 9,
341
- "dynamicTile": {
342
- "enabled": false,
343
- "currentTileSize": 512,
344
- "minTileSize": 256,
345
- "maxTileSize": 512,
346
- "targetTileTimeMs": 16
347
- },
348
- "lastExecution": {
349
- "width": 512,
350
- "height": 512,
351
- "tileWidth": 512,
352
- "tileHeight": 512,
353
- "tileCount": 1,
354
- "durationMs": 30.799999997019768,
355
- "tileTimeMs": {
356
- "min": 30.799999997019768,
357
- "median": 30.799999997019768,
358
- "mean": 30.799999997019768,
359
- "max": 30.799999997019768
360
- }
361
- }
362
- },
363
- "supportsFP16": true,
364
- "adapter": {
365
- "vendor": "apple",
366
- "architecture": "metal-3",
367
- "device": "",
368
- "description": ""
369
- },
370
- "summary": {
371
- "minMs": 29.399999998509884,
372
- "medianMs": 30.30000000447035,
373
- "meanMs": 30.020000000298023,
374
- "p95Ms": 30.399999998509884,
375
- "maxMs": 30.399999998509884
376
- },
377
- "messages": [],
378
- "validation": {
379
- "sampleCount": 6144,
380
- "meanAbsoluteError": 0.0010210334021394374,
381
- "rootMeanSquaredError": 0.001609680379854656,
382
- "maxAbsoluteError": 0.012395620346069336,
383
- "passed": true,
384
- "thresholds": {
385
- "maxMeanError": 0.005,
386
- "maxAbsoluteError": 0.05
387
- }
388
- }
389
- }
390
- ]
391
- }
@@ -1,47 +0,0 @@
1
- # oidn-web benchmark
2
-
3
- - Current: `e6b8577b1c69cc8ce979022717984aec5b9ea881`
4
- - TFJS baseline: `136c00c34aa5cf4561b4137034dbd643177f0a5f`
5
- - Input: 512x512, fixed tile 512, 5 runs after 2 warmup(s)
6
- - Adapter: apple
7
-
8
- | Runtime | Init ms | Median ms | P95 ms | Speedup | Precision |
9
- | --- | ---: | ---: | ---: | ---: | --- |
10
- | TFJS (136c00c) | 8.50 | 37.30 | 37.50 | 1.00x | fp32 |
11
- | WGSL FP32 | 39.40 | 38.10 | 38.20 | 0.98x | fp32 |
12
- | WGSL FP16 | 31.40 | 30.30 | 30.40 | 1.23x | fp16 |
13
-
14
- ## Output validation
15
-
16
- Compared against sampled TFJS FP32 output.
17
-
18
- | Runtime | Status | MAE | RMSE | Max error | Samples |
19
- | --- | --- | ---: | ---: | ---: | ---: |
20
- | WGSL FP32 | pass | 1.11e-6 | 1.81e-6 | 1.36e-5 | 6144 |
21
- | WGSL FP16 | pass | 1.02e-3 | 1.61e-3 | 1.24e-2 | 6144 |
22
-
23
- ## GPU hot layers
24
-
25
- ### WGSL FP32
26
-
27
- Profiled GPU total: 36.71 ms
28
-
29
- | Node | GPU ms |
30
- | --- | ---: |
31
- | dec_conv1a | 7.42 |
32
- | dec_conv2a | 4.37 |
33
- | dec_conv1b | 4.01 |
34
- | enc_conv1b | 3.69 |
35
- | enc_conv2b | 2.70 |
36
-
37
- ### WGSL FP16
38
-
39
- Profiled GPU total: 29.07 ms
40
-
41
- | Node | GPU ms |
42
- | --- | ---: |
43
- | dec_conv1a | 4.44 |
44
- | enc_conv1b | 3.85 |
45
- | dec_conv2a | 3.21 |
46
- | dec_conv1b | 3.09 |
47
- | dec_conv2b | 2.38 |