Skip to content

Commit a7a7d6b

Browse files
authored
Remove Wasm and WebGL backends (WebNN-Polyfill) (#281)
* Remove Wasm and WebGL backends (WebNN-Polyfill) * update README * Remove css class which does not exist in page
1 parent ce57ba9 commit a7a7d6b

Some content is hidden

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

45 files changed

+59
-380
lines changed

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ We welcome contributions from the community to make webnn-samples even better! I
9595
### WebNN Resources
9696
To learn more about Web Neural Network API (WebNN) and its capabilities, check out the following resources:
9797
* [Web Neural Network API Specification](https://webmachinelearning.github.io/webnn/)
98-
* [WebNN Polyfill](https://github.com/webmachinelearning/webnn-polyfill)
99-
* [WebNN Community Group](https://webmachinelearning.github.io/)
98+
* [W3C WebML Working Group and Community Group](https://webmachinelearning.github.io/)
10099

101100
### WebNN API Samples
102101
* [WebNN code editor](https://webmachinelearning.github.io/webnn-samples/code/)

code/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
<script src="./libs/codemirror/codemirror.js"></script>
7171
<script src="./libs/codemirror/javascript.js"></script>
7272
<script src="./libs/codemirror/sublime.js"></script>
73-
<script src="https://webmachinelearning.github.io/webnn-polyfill/dist/webnn-polyfill.js" crossorigin="anonymous"></script>
73+
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js"></script>
7474
<script type="module">
7575
import {main} from './main.js';
7676
window.onload = async () => {

code/main.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import {samplesRepo} from './samples_repo.js';
22
import * as utils from '../common/utils.js';
3+
import {addAlert} from '../common/ui.js';
34

45
window.sizeOfShape = utils.sizeOfShape;
56

67
export async function main() {
78
// Set backend
8-
if (await utils.isWebNN()) {
9-
await utils.setBackend('webnn', 'cpu');
10-
} else {
11-
await utils.setBackend('polyfill', 'cpu');
9+
if (!await utils.isWebNN()) {
10+
console.log(utils.webNNNotSupportMessage());
11+
addAlert(utils.webNNNotSupportMessageHTML());
1212
}
1313
const selectElement = document.getElementById('example-select');
1414
for (const name of samplesRepo.names()) {

common/component/component.js

-7
Original file line numberDiff line numberDiff line change
@@ -599,13 +599,6 @@ $(document).ready(async () => {
599599
$("#footer").html(footer());
600600
if (await isWebNN()) {
601601
if ($("#backendBtns")) {
602-
$('label[name="polyfill"]').addClass("disabled");
603-
$('label[name="polyfill"]').addClass("btn-outline-secondary");
604-
$('label[name="polyfill"]').removeClass("btn-outline-info");
605-
$('label[name="polyfill"]').attr(
606-
"title",
607-
"WebNN is supported, disable WebNN Polyfill."
608-
);
609602
// Disable WebNN NPU backend if failed to find a capable NPU adapter.
610603
try {
611604
await navigator.ml.createContext({deviceType: 'npu'});

common/utils.js

+8-95
Original file line numberDiff line numberDiff line change
@@ -269,48 +269,6 @@ export function getMedianValue(array) {
269269
(array[array.length / 2 - 1] + array[array.length / 2]) / 2;
270270
}
271271

272-
// Set tf.js backend based WebNN's 'MLDeviceType' option
273-
export async function setPolyfillBackend(device) {
274-
// Simulate WebNN's device selection using various tf.js backends.
275-
// MLDeviceType: ['default', 'gpu', 'cpu']
276-
// 'default' or 'gpu': tfjs-backend-webgl, 'cpu': tfjs-backend-wasm
277-
if (!device) device = 'gpu';
278-
// Use 'webgl' by default for better performance.
279-
// Note: 'wasm' backend may run failed on some samples since
280-
// some ops aren't supported on 'wasm' backend at present
281-
const backend = device === 'cpu' ? 'wasm' : 'webgl';
282-
const context = await navigator.ml.createContext();
283-
const tf = context.tf;
284-
if (tf) {
285-
if (backend == 'wasm') {
286-
const wasm = context.wasm;
287-
// Force to use Wasm SIMD only
288-
wasm.setWasmPath(`https://unpkg.com/@tensorflow/tfjs-backend-wasm@${tf.version_core}/dist/tfjs-backend-wasm-simd.wasm`);
289-
}
290-
if (!(await tf.setBackend(backend))) {
291-
throw new Error(`Failed to set tf.js backend ${backend}.`);
292-
}
293-
await tf.ready();
294-
let backendInfo = backend == 'wasm' ? 'WASM' : 'WebGL';
295-
if (backendInfo == 'WASM') {
296-
const hasSimd = tf.env().features['WASM_HAS_SIMD_SUPPORT'];
297-
const hasThreads = tf.env().features['WASM_HAS_MULTITHREAD_SUPPORT'];
298-
if (hasThreads && hasSimd) {
299-
backendInfo += ' (SIMD + threads)';
300-
} else if (hasThreads && !hasSimd) {
301-
backendInfo += ' (threads)';
302-
} else if (!hasThreads && hasSimd) {
303-
backendInfo += ' (SIMD)';
304-
}
305-
}
306-
addAlert(
307-
`This sample is running on ` +
308-
`<a href='https://github.com/webmachinelearning/webnn-polyfill'>` +
309-
`WebNN-polyfill</a> with tf.js ${tf.version_core} ` +
310-
`<b>${backendInfo}</b> backend.`, 'info');
311-
}
312-
}
313-
314272
// Get url params
315273
export function getUrlParams() {
316274
const params = new URLSearchParams(location.search);
@@ -346,59 +304,6 @@ export function getUrlParams() {
346304
return [numRuns, powerPreference, numThreads];
347305
}
348306

349-
// Set backend for using WebNN-polyfill or WebNN
350-
export async function setBackend(backend, device) {
351-
const webnnPolyfillId = 'webnn_polyfill';
352-
const webnnNodeId = 'webnn_node';
353-
const webnnPolyfillElem = document.getElementById(webnnPolyfillId);
354-
const webnnNodeElem = document.getElementById(webnnNodeId);
355-
356-
if (backend === 'polyfill') {
357-
if (webnnNodeElem) {
358-
document.body.removeChild(webnnNodeElem);
359-
// Unset global objects defined in node_setup.js
360-
global.navigator.ml = undefined;
361-
global.MLContext = undefined;
362-
global.MLGraphBuilder = undefined;
363-
global.MLGraph = undefined;
364-
global.MLOperand = undefined;
365-
}
366-
if (!webnnPolyfillElem) {
367-
const webnnPolyfillUrl =
368-
'https://webmachinelearning.github.io/webnn-polyfill/dist/webnn-polyfill.js';
369-
if (typeof(tf) != 'undefined') {
370-
// Reset tf.ENV to avoid environments from tf.min.js
371-
// affect webnn-polyfill.js
372-
tf.engine().reset();
373-
}
374-
// Create WebNN-polyfill script
375-
await loadScript(webnnPolyfillUrl, webnnPolyfillId);
376-
}
377-
await setPolyfillBackend(device);
378-
} else if (backend === 'webnn') {
379-
if (!await isWebNN()) {
380-
addAlert(`WebNN is not supported!`, 'warning');
381-
}
382-
} else {
383-
addAlert(`Unknow backend: ${backend}`, 'warning');
384-
}
385-
}
386-
387-
// Promise to load script with url and id
388-
async function loadScript(url, id) {
389-
return new Promise((resolve, reject) => {
390-
const script = document.createElement('script');
391-
script.onload = resolve;
392-
script.onerror = reject;
393-
script.src = url;
394-
script.id = id;
395-
if (url.startsWith('http')) {
396-
script.crossOrigin = 'anonymous';
397-
}
398-
document.body.appendChild(script);
399-
});
400-
}
401-
402307
export async function isWebNN() {
403308
if (typeof MLGraphBuilder !== 'undefined') {
404309
const context = await navigator.ml.createContext();
@@ -408,6 +313,14 @@ export async function isWebNN() {
408313
}
409314
}
410315

316+
export function webNNNotSupportMessage() {
317+
return 'Your browser does not support WebNN.';
318+
}
319+
320+
export function webNNNotSupportMessageHTML() {
321+
return 'Your browser does not support WebNN. Please refer to <a href="https://github.com/webmachinelearning/webnn-samples/#webnn-installation-guides">WebNN Installation Guides</a> for more details.';
322+
}
323+
411324
// Derive from
412325
// https://github.com/webmachinelearning/webnn-baseline/blob/main/src/lib/compute-padding.js
413326
/**

face_recognition/facenet_nchw.js

-8
Original file line numberDiff line numberDiff line change
@@ -276,14 +276,6 @@ export class FaceNetNchw {
276276
this.graph_ = await this.builder_.build({'output': outputOperand});
277277
}
278278

279-
// Release the constant tensors of a model
280-
dispose() {
281-
// dispose() is only available in webnn-polyfill
282-
if (this.graph_ !== null && 'dispose' in this.graph_) {
283-
this.graph_.dispose();
284-
}
285-
}
286-
287279
async compute(inputBuffer) {
288280
this.context_.writeTensor(this.inputTensor_, inputBuffer);
289281
const inputs = {'input': this.inputTensor_};

face_recognition/facenet_nhwc.js

-8
Original file line numberDiff line numberDiff line change
@@ -245,14 +245,6 @@ export class FaceNetNhwc {
245245
this.graph_ = await this.builder_.build({'output': outputOperand});
246246
}
247247

248-
// Release the constant tensors of a model
249-
dispose() {
250-
// dispose() is only available in webnn-polyfill
251-
if (this.graph_ !== null && 'dispose' in this.graph_) {
252-
this.graph_.dispose();
253-
}
254-
}
255-
256248
async compute(inputBuffer) {
257249
this.context_.writeTensor(this.inputTensor_, inputBuffer);
258250
const inputs = {'input': this.inputTensor_};

face_recognition/index.html

-6
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,6 @@
3131
</div>
3232
<div class="col-md-auto">
3333
<div class="btn-group-toggle" data-toggle="buttons" id="backendBtns">
34-
<label class="btn btn-outline-info custom" name="polyfill">
35-
<input type="radio" name="backend" id="polyfill_cpu" autocomplete="off">Wasm (CPU)
36-
</label>
37-
<label class="btn btn-outline-info custom" name="polyfill">
38-
<input type="radio" name="backend" id="polyfill_gpu" autocomplete="off">WebGL (GPU)
39-
</label>
4034
<label class="btn btn-outline-info custom" name="webnn">
4135
<input type="radio" name="backend" id="webnn_cpu" autocomplete="off">WebNN (CPU)
4236
</label>

face_recognition/main.js

+2-10
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ $(document).ready(async () => {
4545
if (await utils.isWebNN()) {
4646
$('#webnn_cpu').click();
4747
} else {
48-
$('#polyfill_cpu').click();
48+
console.log(utils.webNNNotSupportMessage());
49+
ui.addAlert(utils.webNNNotSupportMessageHTML());
4950
}
5051
});
5152

@@ -307,19 +308,10 @@ async function main() {
307308
lastdeviceType != deviceType || lastBackend != backend) {
308309
if (lastdeviceType != deviceType || lastBackend != backend) {
309310
// Set backend and device
310-
await utils.setBackend(backend, deviceType);
311311
lastdeviceType = lastdeviceType != deviceType ?
312312
deviceType : lastdeviceType;
313313
lastBackend = lastBackend != backend ? backend : lastBackend;
314314
}
315-
if (frInstance !== null) {
316-
// Call dispose() to and avoid memory leak
317-
frInstance.dispose();
318-
}
319-
if (fdInstance !== null) {
320-
// Call dispose() to and avoid memory leak
321-
fdInstance.dispose();
322-
}
323315
fdInstanceType = fdModelName + layout;
324316
frInstanceType = frModelName + layout;
325317
fdInstance = constructNetObject(fdInstanceType);

facial_landmark_detection/face_landmark_nchw.js

-8
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,6 @@ export class FaceLandmarkNchw {
116116
this.graph_ = await this.builder_.build({'output': outputOperand});
117117
}
118118

119-
// Release the constant tensors of a model
120-
dispose() {
121-
// dispose() is only available in webnn-polyfill
122-
if (this.graph_ !== null && 'dispose' in this.graph_) {
123-
this.graph_.dispose();
124-
}
125-
}
126-
127119
async compute(inputBuffer) {
128120
this.context_.writeTensor(this.inputTensor_, inputBuffer);
129121
const inputs = {'input': this.inputTensor_};

facial_landmark_detection/face_landmark_nhwc.js

-8
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,6 @@ export class FaceLandmarkNhwc {
119119
this.graph_ = await this.builder_.build({'output': outputOperand});
120120
}
121121

122-
// Release the constant tensors of a model
123-
dispose() {
124-
// dispose() is only available in webnn-polyfill
125-
if (this.graph_ !== null && 'dispose' in this.graph_) {
126-
this.graph_.dispose();
127-
}
128-
}
129-
130122
async compute(inputBuffer) {
131123
this.context_.writeTensor(this.inputTensor_, inputBuffer);
132124
const inputs = {'input': this.inputTensor_};

facial_landmark_detection/index.html

-6
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,6 @@
3131
</div>
3232
<div class="col-md-auto">
3333
<div class="btn-group-toggle" data-toggle="buttons" id="backendBtns">
34-
<label class="btn btn-outline-info custom" name="polyfill">
35-
<input type="radio" name="backend" id="polyfill_cpu" autocomplete="off">Wasm (CPU)
36-
</label>
37-
<label class="btn btn-outline-info custom" name="polyfill">
38-
<input type="radio" name="backend" id="polyfill_gpu" autocomplete="off">WebGL (GPU)
39-
</label>
4034
<label class="btn btn-outline-info custom" name="webnn">
4135
<input type="radio" name="backend" id="webnn_cpu" autocomplete="off">WebNN (CPU)
4236
</label>

facial_landmark_detection/main.js

+2-10
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ $(document).ready(async () => {
4141
if (await utils.isWebNN()) {
4242
$('#webnn_cpu').click();
4343
} else {
44-
$('#polyfill_cpu').click();
44+
console.log(utils.webNNNotSupportMessage());
45+
ui.addAlert(utils.webNNNotSupportMessageHTML());
4546
}
4647
});
4748

@@ -243,19 +244,10 @@ async function main() {
243244
lastdeviceType != deviceType || lastBackend != backend) {
244245
if (lastdeviceType != deviceType || lastBackend != backend) {
245246
// Set backend and device
246-
await utils.setBackend(backend, deviceType);
247247
lastdeviceType = lastdeviceType != deviceType ?
248248
deviceType : lastdeviceType;
249249
lastBackend = lastBackend != backend ? backend : lastBackend;
250250
}
251-
if (fldInstance !== null) {
252-
// Call dispose() to and avoid memory leak
253-
fldInstance.dispose();
254-
}
255-
if (fdInstance !== null) {
256-
// Call dispose() to and avoid memory leak
257-
fdInstance.dispose();
258-
}
259251
fdInstanceType = fdModelName + layout;
260252
fldInstanceType = fldModelName + layout;
261253
fdInstance = constructNetObject(fdInstanceType);

facial_landmark_detection/ssd_mobilenetv2_face_nchw.js

-8
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,6 @@ ${nameArray[1]}`;
243243
this.graph_ = await this.builder_.build(outputOperand);
244244
}
245245

246-
// Release the constant tensors of a model
247-
dispose() {
248-
// dispose() is only available in webnn-polyfill
249-
if (this.graph_ !== null && 'dispose' in this.graph_) {
250-
this.graph_.dispose();
251-
}
252-
}
253-
254246
async compute(inputBuffer) {
255247
this.context_.writeTensor(this.inputTensor_, inputBuffer);
256248
const inputs = {'input': this.inputTensor_};

facial_landmark_detection/ssd_mobilenetv2_face_nhwc.js

-8
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,6 @@ ${nameArray[1]}`;
255255
this.graph_ = await this.builder_.build(outputOperand);
256256
}
257257

258-
// Release the constant tensors of a model
259-
dispose() {
260-
// dispose() is only available in webnn-polyfill
261-
if (this.graph_ !== null && 'dispose' in this.graph_) {
262-
this.graph_.dispose();
263-
}
264-
}
265-
266258
async compute(inputBuffer) {
267259
this.context_.writeTensor(this.inputTensor_, inputBuffer);
268260
const inputs = {'input': this.inputTensor_};

image_classification/efficientnet_fp16_nchw.js

-8
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,6 @@ export class EfficientNetFP16Nchw {
168168
this.graph_ = await this.builder_.build({'output': outputOperand});
169169
}
170170

171-
// Release the constant tensors of a model
172-
dispose() {
173-
// dispose() is only available in webnn-polyfill
174-
if (this.graph_ !== null && 'dispose' in this.graph_) {
175-
this.graph_.dispose();
176-
}
177-
}
178-
179171
async compute(inputBuffer) {
180172
this.context_.writeTensor(this.inputTensor_, inputBuffer);
181173
const inputs = {'input': this.inputTensor_};

image_classification/index.html

-6
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,6 @@
3131
</div>
3232
<div class="col-md-auto">
3333
<div class="btn-group-toggle" data-toggle="buttons" id="backendBtns">
34-
<label class="btn btn-outline-info custom" name="polyfill">
35-
<input type="radio" name="backend" id="polyfill_cpu" autocomplete="off">Wasm (CPU)
36-
</label>
37-
<label class="btn btn-outline-info custom" name="polyfill">
38-
<input type="radio" name="backend" id="polyfill_gpu" autocomplete="off">WebGL (GPU)
39-
</label>
4034
<label class="btn btn-outline-info custom" name="webnn">
4135
<input type="radio" name="backend" id="webnn_cpu" autocomplete="off">WebNN (CPU)
4236
</label>

0 commit comments

Comments
 (0)