Skip to content

Commit c8a751c

Browse files
authored
Enable WebNN GPU backend (#181)
1 parent ad03c8c commit c8a751c

18 files changed

Lines changed: 105 additions & 38 deletions

File tree

common/component/component.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -590,13 +590,6 @@ $(document).ready(async () => {
590590
"title",
591591
"WebNN is supported, disable WebNN Polyfill."
592592
);
593-
$('label:contains("WebNN (GPU)")').addClass("disabled");
594-
$('label:contains("WebNN (GPU)")').addClass("btn-outline-secondary");
595-
$('label:contains("WebNN (GPU)")').removeClass("btn-outline-info");
596-
$('label:contains("WebNN (GPU)")').attr(
597-
"title",
598-
"WebNN GPU backend is not supported."
599-
);
600593
}
601594
}
602595
$("#webnnstatus").html("supported").addClass("webnn-status-true");

face_recognition/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ async function main() {
310310
// UI shows model loading progress
311311
await ui.showProgressComponent('current', 'pending', 'pending');
312312
console.log('- Loading weights... ');
313-
const contextOptions = {deviceType};
313+
const contextOptions = {'devicePreference': deviceType};
314314
if (powerPreference) {
315315
contextOptions['powerPreference'] = powerPreference;
316316
}

facial_landmark_detection/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ async function main() {
245245
// UI shows model loading progress
246246
await ui.showProgressComponent('current', 'pending', 'pending');
247247
console.log('- Loading weights... ');
248-
const contextOptions = {deviceType};
248+
const contextOptions = {'devicePreference': deviceType};
249249
if (powerPreference) {
250250
contextOptions['powerPreference'] = powerPreference;
251251
}

facial_landmark_detection/ssd_mobilenetv2_face_nchw.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {buildConstantByNpy} from '../common/utils.js';
66
export class SsdMobilenetV2FaceNchw {
77
constructor() {
88
this.context_ = null;
9+
this.devicePreference_ = null;
910
this.builder_ = null;
1011
this.graph_ = null;
1112
this.weightsUrl_ = '../test-data/models/ssd_mobilenetv2_face_nchw/weights/';
@@ -74,8 +75,16 @@ ${nameArray[1]}`;
7475
}
7576
options.bias = bias;
7677
if (clip) {
77-
// implement `clip` by `clamp` of WebNN API
78-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
78+
// TODO: Set clamp activation to options once it's supported in
79+
// WebNN DML backend.
80+
// Implement `clip` by `clamp` of WebNN API
81+
if (this.devicePreference_ == 'gpu') {
82+
return this.builder_.clamp(
83+
this.builder_.conv2d(input, weights, options),
84+
{minValue: 0, maxValue: 6});
85+
} else {
86+
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
87+
}
7988
}
8089
return this.builder_.conv2d(input, weights, options);
8190
}
@@ -110,6 +119,7 @@ ${nameArray[1]}`;
110119

111120
async load(contextOptions) {
112121
this.context_ = await navigator.ml.createContext(contextOptions);
122+
this.devicePreference_ = contextOptions.devicePreference;
113123
this.builder_ = new MLGraphBuilder(this.context_);
114124
const input = this.builder_.input('input',
115125
{type: 'float32', dimensions: this.inputOptions.inputDimensions});

facial_landmark_detection/ssd_mobilenetv2_face_nhwc.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {buildConstantByNpy} from '../common/utils.js';
66
export class SsdMobilenetV2FaceNhwc {
77
constructor() {
88
this.context_ = null;
9+
this.devicePreference_ = null;
910
this.builder_ = null;
1011
this.graph_ = null;
1112
this.weightsUrl_ = '../test-data/models/ssd_mobilenetv2_face_nhwc/weights/';
@@ -81,8 +82,16 @@ ${nameArray[1]}`;
8182
}
8283
options.bias = bias;
8384
if (relu6) {
84-
// implement `relu6` by `clamp` of WebNN API
85-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
85+
// TODO: Set clamp activation to options once it's supported in
86+
// WebNN DML backend.
87+
// Implement `clip` by `clamp` of WebNN API
88+
if (this.devicePreference_ == 'gpu') {
89+
return this.builder_.clamp(
90+
this.builder_.conv2d(input, weights, options),
91+
{minValue: 0, maxValue: 6});
92+
} else {
93+
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
94+
}
8695
}
8796
return this.builder_.conv2d(input, weights, options);
8897
}
@@ -117,6 +126,7 @@ ${nameArray[1]}`;
117126

118127
async load(contextOptions) {
119128
this.context_ = await navigator.ml.createContext(contextOptions);
129+
this.devicePreference_ = contextOptions.devicePreference;
120130
this.builder_ = new MLGraphBuilder(this.context_);
121131
const input = this.builder_.input('input',
122132
{type: 'float32', dimensions: this.inputOptions.inputDimensions});

image_classification/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ async function main() {
231231
// UI shows model loading progress
232232
await ui.showProgressComponent('current', 'pending', 'pending');
233233
console.log('- Loading weights... ');
234-
const contextOptions = {deviceType};
234+
const contextOptions = {'devicePreference': deviceType};
235235
if (powerPreference) {
236236
contextOptions['powerPreference'] = powerPreference;
237237
}

image_classification/mobilenet_nchw.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {buildConstantByNpy} from '../common/utils.js';
66
export class MobileNetV2Nchw {
77
constructor() {
88
this.context_ = null;
9+
this.devicePreference_ = null;
910
this.builder_ = null;
1011
this.graph_ = null;
1112
this.weightsUrl_ = '../test-data/models/mobilenetv2_nchw/weights/';
@@ -30,10 +31,16 @@ export class MobileNetV2Nchw {
3031
await buildConstantByNpy(this.builder_, biasName);
3132
options.bias = bias;
3233
if (relu6) {
33-
// implement `relu6` by `clamp` of WebNN API
34-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
35-
} else {
36-
options.activation = undefined;
34+
// TODO: Set clamp activation to options once it's supported in
35+
// WebNN DML backend.
36+
// Implement `clip` by `clamp` of WebNN API
37+
if (this.devicePreference_ == 'gpu') {
38+
return this.builder_.clamp(
39+
this.builder_.conv2d(input, weights, options),
40+
{minValue: 0, maxValue: 6});
41+
} else {
42+
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
43+
}
3744
}
3845
return this.builder_.conv2d(input, weights, options);
3946
}
@@ -69,6 +76,7 @@ export class MobileNetV2Nchw {
6976

7077
async load(contextOptions) {
7178
this.context_ = await navigator.ml.createContext(contextOptions);
79+
this.devicePreference_ = contextOptions.devicePreference;
7280
this.builder_ = new MLGraphBuilder(this.context_);
7381
const data = this.builder_.input('input',
7482
{type: 'float32', dimensions: this.inputOptions.inputDimensions});

image_classification/mobilenet_nhwc.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {buildConstantByNpy} from '../common/utils.js';
88
export class MobileNetV2Nhwc {
99
constructor() {
1010
this.context_ = null;
11+
this.devicePreference_ = null;
1112
this.builder_ = null;
1213
this.graph_ = null;
1314
this.weightsUrl_ = '../test-data/models/mobilenetv2_nhwc/weights/';
@@ -29,10 +30,16 @@ export class MobileNetV2Nhwc {
2930
options.inputLayout = 'nhwc';
3031
options.bias = bias;
3132
if (relu6) {
32-
// `relu6` in TFLite equals to `clamp` in WebNN API
33-
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
34-
} else {
35-
options.activation = undefined;
33+
// TODO: Set clamp activation to options once it's supported in
34+
// WebNN DML backend.
35+
// Implement `clip` by `clamp` of WebNN API
36+
if (this.devicePreference_ == 'gpu') {
37+
return this.builder_.clamp(
38+
this.builder_.conv2d(input, weights, options),
39+
{minValue: 0, maxValue: 6});
40+
} else {
41+
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
42+
}
3643
}
3744
return this.builder_.conv2d(input, weights, options);
3845
}
@@ -60,6 +67,7 @@ export class MobileNetV2Nhwc {
6067

6168
async load(contextOptions) {
6269
this.context_ = await navigator.ml.createContext(contextOptions);
70+
this.devicePreference_ = contextOptions.devicePreference;
6371
this.builder_ = new MLGraphBuilder(this.context_);
6472
const strides = [2, 2];
6573
const autoPad = 'same-upper';

lenet/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ async function main() {
6868
const lenet = new LeNet(weightUrl);
6969
const [numRuns, powerPreference, numThreads] = utils.getUrlParams();
7070
try {
71-
const contextOptions = {deviceType};
71+
const contextOptions = {'devicePreference': deviceType};
7272
if (powerPreference) {
7373
contextOptions['powerPreference'] = powerPreference;
7474
}

nsnet2/denoiser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class Denoiser {
3131
const start = performance.now();
3232
const weightsUrl = '../test-data/models/nsnet2/weights/';
3333
const powerPreference = getUrlParams()[1];
34-
const contextOptions = {deviceType};
34+
const contextOptions = {'devicePreference': deviceType};
3535
if (powerPreference) {
3636
contextOptions['powerPreference'] = powerPreference;
3737
}

0 commit comments

Comments
 (0)