Skip to content

Commit

Permalink
Enable WebNN GPU backend (#181)
Browse files Browse the repository at this point in the history
  • Loading branch information
Honry authored Sep 25, 2023
1 parent ad03c8c commit c8a751c
Show file tree
Hide file tree
Showing 18 changed files with 105 additions and 38 deletions.
7 changes: 0 additions & 7 deletions common/component/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -590,13 +590,6 @@ $(document).ready(async () => {
"title",
"WebNN is supported, disable WebNN Polyfill."
);
$('label:contains("WebNN (GPU)")').addClass("disabled");
$('label:contains("WebNN (GPU)")').addClass("btn-outline-secondary");
$('label:contains("WebNN (GPU)")').removeClass("btn-outline-info");
$('label:contains("WebNN (GPU)")').attr(
"title",
"WebNN GPU backend is not supported."
);
}
}
$("#webnnstatus").html("supported").addClass("webnn-status-true");
Expand Down
2 changes: 1 addition & 1 deletion face_recognition/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ async function main() {
// UI shows model loading progress
await ui.showProgressComponent('current', 'pending', 'pending');
console.log('- Loading weights... ');
const contextOptions = {deviceType};
const contextOptions = {'devicePreference': deviceType};
if (powerPreference) {
contextOptions['powerPreference'] = powerPreference;
}
Expand Down
2 changes: 1 addition & 1 deletion facial_landmark_detection/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ async function main() {
// UI shows model loading progress
await ui.showProgressComponent('current', 'pending', 'pending');
console.log('- Loading weights... ');
const contextOptions = {deviceType};
const contextOptions = {'devicePreference': deviceType};
if (powerPreference) {
contextOptions['powerPreference'] = powerPreference;
}
Expand Down
14 changes: 12 additions & 2 deletions facial_landmark_detection/ssd_mobilenetv2_face_nchw.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {buildConstantByNpy} from '../common/utils.js';
export class SsdMobilenetV2FaceNchw {
constructor() {
this.context_ = null;
this.devicePreference_ = null;
this.builder_ = null;
this.graph_ = null;
this.weightsUrl_ = '../test-data/models/ssd_mobilenetv2_face_nchw/weights/';
Expand Down Expand Up @@ -74,8 +75,16 @@ ${nameArray[1]}`;
}
options.bias = bias;
if (clip) {
// implement `clip` by `clamp` of WebNN API
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
// TODO: Set clamp activation to options once it's supported in
// WebNN DML backend.
// Implement `clip` by `clamp` of WebNN API
if (this.devicePreference_ == 'gpu') {
return this.builder_.clamp(
this.builder_.conv2d(input, weights, options),
{minValue: 0, maxValue: 6});
} else {
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
}
}
return this.builder_.conv2d(input, weights, options);
}
Expand Down Expand Up @@ -110,6 +119,7 @@ ${nameArray[1]}`;

async load(contextOptions) {
this.context_ = await navigator.ml.createContext(contextOptions);
this.devicePreference_ = contextOptions.devicePreference;
this.builder_ = new MLGraphBuilder(this.context_);
const input = this.builder_.input('input',
{type: 'float32', dimensions: this.inputOptions.inputDimensions});
Expand Down
14 changes: 12 additions & 2 deletions facial_landmark_detection/ssd_mobilenetv2_face_nhwc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {buildConstantByNpy} from '../common/utils.js';
export class SsdMobilenetV2FaceNhwc {
constructor() {
this.context_ = null;
this.devicePreference_ = null;
this.builder_ = null;
this.graph_ = null;
this.weightsUrl_ = '../test-data/models/ssd_mobilenetv2_face_nhwc/weights/';
Expand Down Expand Up @@ -81,8 +82,16 @@ ${nameArray[1]}`;
}
options.bias = bias;
if (relu6) {
// implement `relu6` by `clamp` of WebNN API
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
// TODO: Set clamp activation to options once it's supported in
// WebNN DML backend.
// Implement `clip` by `clamp` of WebNN API
if (this.devicePreference_ == 'gpu') {
return this.builder_.clamp(
this.builder_.conv2d(input, weights, options),
{minValue: 0, maxValue: 6});
} else {
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
}
}
return this.builder_.conv2d(input, weights, options);
}
Expand Down Expand Up @@ -117,6 +126,7 @@ ${nameArray[1]}`;

async load(contextOptions) {
this.context_ = await navigator.ml.createContext(contextOptions);
this.devicePreference_ = contextOptions.devicePreference;
this.builder_ = new MLGraphBuilder(this.context_);
const input = this.builder_.input('input',
{type: 'float32', dimensions: this.inputOptions.inputDimensions});
Expand Down
2 changes: 1 addition & 1 deletion image_classification/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ async function main() {
// UI shows model loading progress
await ui.showProgressComponent('current', 'pending', 'pending');
console.log('- Loading weights... ');
const contextOptions = {deviceType};
const contextOptions = {'devicePreference': deviceType};
if (powerPreference) {
contextOptions['powerPreference'] = powerPreference;
}
Expand Down
16 changes: 12 additions & 4 deletions image_classification/mobilenet_nchw.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {buildConstantByNpy} from '../common/utils.js';
export class MobileNetV2Nchw {
constructor() {
this.context_ = null;
this.devicePreference_ = null;
this.builder_ = null;
this.graph_ = null;
this.weightsUrl_ = '../test-data/models/mobilenetv2_nchw/weights/';
Expand All @@ -30,10 +31,16 @@ export class MobileNetV2Nchw {
await buildConstantByNpy(this.builder_, biasName);
options.bias = bias;
if (relu6) {
// implement `relu6` by `clamp` of WebNN API
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
} else {
options.activation = undefined;
// TODO: Set clamp activation to options once it's supported in
// WebNN DML backend.
// Implement `clip` by `clamp` of WebNN API
if (this.devicePreference_ == 'gpu') {
return this.builder_.clamp(
this.builder_.conv2d(input, weights, options),
{minValue: 0, maxValue: 6});
} else {
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
}
}
return this.builder_.conv2d(input, weights, options);
}
Expand Down Expand Up @@ -69,6 +76,7 @@ export class MobileNetV2Nchw {

async load(contextOptions) {
this.context_ = await navigator.ml.createContext(contextOptions);
this.devicePreference_ = contextOptions.devicePreference;
this.builder_ = new MLGraphBuilder(this.context_);
const data = this.builder_.input('input',
{type: 'float32', dimensions: this.inputOptions.inputDimensions});
Expand Down
16 changes: 12 additions & 4 deletions image_classification/mobilenet_nhwc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {buildConstantByNpy} from '../common/utils.js';
export class MobileNetV2Nhwc {
constructor() {
this.context_ = null;
this.devicePreference_ = null;
this.builder_ = null;
this.graph_ = null;
this.weightsUrl_ = '../test-data/models/mobilenetv2_nhwc/weights/';
Expand All @@ -29,10 +30,16 @@ export class MobileNetV2Nhwc {
options.inputLayout = 'nhwc';
options.bias = bias;
if (relu6) {
// `relu6` in TFLite equals to `clamp` in WebNN API
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
} else {
options.activation = undefined;
// TODO: Set clamp activation to options once it's supported in
// WebNN DML backend.
// Implement `clip` by `clamp` of WebNN API
if (this.devicePreference_ == 'gpu') {
return this.builder_.clamp(
this.builder_.conv2d(input, weights, options),
{minValue: 0, maxValue: 6});
} else {
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
}
}
return this.builder_.conv2d(input, weights, options);
}
Expand Down Expand Up @@ -60,6 +67,7 @@ export class MobileNetV2Nhwc {

async load(contextOptions) {
this.context_ = await navigator.ml.createContext(contextOptions);
this.devicePreference_ = contextOptions.devicePreference;
this.builder_ = new MLGraphBuilder(this.context_);
const strides = [2, 2];
const autoPad = 'same-upper';
Expand Down
2 changes: 1 addition & 1 deletion lenet/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ async function main() {
const lenet = new LeNet(weightUrl);
const [numRuns, powerPreference, numThreads] = utils.getUrlParams();
try {
const contextOptions = {deviceType};
const contextOptions = {'devicePreference': deviceType};
if (powerPreference) {
contextOptions['powerPreference'] = powerPreference;
}
Expand Down
2 changes: 1 addition & 1 deletion nsnet2/denoiser.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class Denoiser {
const start = performance.now();
const weightsUrl = '../test-data/models/nsnet2/weights/';
const powerPreference = getUrlParams()[1];
const contextOptions = {deviceType};
const contextOptions = {'devicePreference': deviceType};
if (powerPreference) {
contextOptions['powerPreference'] = powerPreference;
}
Expand Down
2 changes: 1 addition & 1 deletion object_detection/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ async function main() {
// UI shows model loading progress
await ui.showProgressComponent('current', 'pending', 'pending');
console.log('- Loading weights... ');
const contextOptions = {deviceType};
const contextOptions = {'devicePreference': deviceType};
if (powerPreference) {
contextOptions['powerPreference'] = powerPreference;
}
Expand Down
14 changes: 12 additions & 2 deletions object_detection/ssd_mobilenetv1_nchw.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {buildConstantByNpy} from '../common/utils.js';
export class SsdMobilenetV1Nchw {
constructor() {
this.context_ = null;
this.devicePreference_ = null;
this.model_ = null;
this.builder_ = null;
this.graph_ = null;
Expand Down Expand Up @@ -60,14 +61,23 @@ ${nameArray[1]}_BatchNorm_batchnorm`;
options.autoPad = 'same-upper';
options.bias = bias;
if (relu6) {
// implement `relu6` by `clamp` of WebNN API
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
// TODO: Set clamp activation to options once it's supported in
// WebNN DML backend.
// Implement `clip` by `clamp` of WebNN API
if (this.devicePreference_ == 'gpu') {
return this.builder_.clamp(
this.builder_.conv2d(input, weights, options),
{minValue: 0, maxValue: 6});
} else {
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
}
}
return this.builder_.conv2d(input, weights, options);
}

async load(contextOptions) {
this.context_ = await navigator.ml.createContext(contextOptions);
this.devicePreference_ = contextOptions.devicePreference;
this.builder_ = new MLGraphBuilder(this.context_);
const input = this.builder_.input('input',
{type: 'float32', dimensions: this.inputOptions.inputDimensions});
Expand Down
14 changes: 12 additions & 2 deletions object_detection/ssd_mobilenetv1_nhwc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {buildConstantByNpy} from '../common/utils.js';
export class SsdMobilenetV1Nhwc {
constructor() {
this.context_ = null;
this.devicePreference_ = null;
this.model_ = null;
this.builder_ = null;
this.graph_ = null;
Expand Down Expand Up @@ -71,14 +72,23 @@ ${nameArray[1]}_BatchNorm_batchnorm`;
}
options.bias = bias;
if (relu6) {
// implement `relu6` by `clamp` of WebNN API
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
// TODO: Set clamp activation to options once it's supported in
// WebNN DML backend.
// Implement `clip` by `clamp` of WebNN API
if (this.devicePreference_ == 'gpu') {
return this.builder_.clamp(
this.builder_.conv2d(input, weights, options),
{minValue: 0, maxValue: 6});
} else {
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
}
}
return this.builder_.conv2d(input, weights, options);
}

async load(contextOptions) {
this.context_ = await navigator.ml.createContext(contextOptions);
this.devicePreference_ = contextOptions.devicePreference;
this.builder_ = new MLGraphBuilder(this.context_);
const input = this.builder_.input('input',
{type: 'float32', dimensions: this.inputOptions.inputDimensions});
Expand Down
2 changes: 1 addition & 1 deletion rnnoise/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export async function main() {
`[${batchSize} (batch_size) x 100 (frames) x 42].`, true);
await log(modelInfo, '- Loading model...');
const powerPreference = utils.getUrlParams()[1];
const contextOptions = {deviceType};
const contextOptions = {'devicePreference': deviceType};
if (powerPreference) {
contextOptions['powerPreference'] = powerPreference;
}
Expand Down
14 changes: 12 additions & 2 deletions semantic_segmentation/deeplabv3_mnv2_nchw.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {buildConstantByNpy} from '../common/utils.js';
export class DeepLabV3MNV2Nchw {
constructor() {
this.context_ = null;
this.devicePreference_ = null;
this.builder_ = null;
this.graph_ = null;
this.weightsUrl_ = '../test-data/models/deeplabv3_mnv2_nchw/weights/';
Expand Down Expand Up @@ -43,8 +44,16 @@ export class DeepLabV3MNV2Nchw {

options.bias = bias;
if (activation === 'relu6') {
// implement `relu6` by `clamp` of WebNN API
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
// TODO: Set clamp activation to options once it's supported in
// WebNN DML backend.
// Implement `clip` by `clamp` of WebNN API
if (this.devicePreference_ == 'gpu') {
return this.builder_.clamp(
this.builder_.conv2d(input, weights, options),
{minValue: 0, maxValue: 6});
} else {
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
}
} else if (activation === 'relu') {
options.activation = this.builder_.relu();
} else {
Expand Down Expand Up @@ -82,6 +91,7 @@ export class DeepLabV3MNV2Nchw {

async load(contextOptions) {
this.context_ = await navigator.ml.createContext(contextOptions);
this.devicePreference_ = contextOptions.devicePreference;
this.builder_ = new MLGraphBuilder(this.context_);
const strides = [2, 2];

Expand Down
16 changes: 12 additions & 4 deletions semantic_segmentation/deeplabv3_mnv2_nhwc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {buildConstantByNpy} from '../common/utils.js';
export class DeepLabV3MNV2Nhwc {
constructor() {
this.context_ = null;
this.devicePreference_ = null;
this.builder_ = null;
this.graph_ = null;
this.weightsUrl_ = '../test-data/models/deeplabv3_mnv2_nhwc/weights/';
Expand Down Expand Up @@ -43,10 +44,16 @@ export class DeepLabV3MNV2Nhwc {
}
options.bias = bias;
if (relu6) {
// `relu6` in TFLite equals to `clamp` in WebNN API
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
} else {
options.activation = undefined;
// TODO: Set clamp activation to options once it's supported in
// WebNN DML backend.
// Implement `clip` by `clamp` of WebNN API
if (this.devicePreference_ == 'gpu') {
return this.builder_.clamp(
this.builder_.conv2d(input, weights, options),
{minValue: 0, maxValue: 6});
} else {
options.activation = this.builder_.clamp({minValue: 0, maxValue: 6});
}
}
return this.builder_.conv2d(input, weights, options);
}
Expand All @@ -73,6 +80,7 @@ export class DeepLabV3MNV2Nhwc {

async load(contextOptions) {
this.context_ = await navigator.ml.createContext(contextOptions);
this.devicePreference_ = contextOptions.devicePreference;
this.builder_ = new MLGraphBuilder(this.context_);
const strides = [2, 2];
const input = this.builder_.input('input',
Expand Down
2 changes: 1 addition & 1 deletion semantic_segmentation/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ export async function main() {
// UI shows model loading progress
await ui.showProgressComponent('current', 'pending', 'pending');
console.log('- Loading weights... ');
const contextOptions = {deviceType};
const contextOptions = {'devicePreference': deviceType};
if (powerPreference) {
contextOptions['powerPreference'] = powerPreference;
}
Expand Down
2 changes: 1 addition & 1 deletion style_transfer/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export async function main() {
// UI shows model loading progress
await ui.showProgressComponent('current', 'pending', 'pending');
console.log('- Loading weights... ');
const contextOptions = {deviceType};
const contextOptions = {'devicePreference': deviceType};
if (powerPreference) {
contextOptions['powerPreference'] = powerPreference;
}
Expand Down

0 comments on commit c8a751c

Please sign in to comment.