diff --git a/face_recognition/main.js b/face_recognition/main.js index 079b78a5..0a35aafa 100644 --- a/face_recognition/main.js +++ b/face_recognition/main.js @@ -325,16 +325,21 @@ async function main() { contextOptions['numThreads'] = numThreads; } start = performance.now(); - const fdOutputOperand = await fdInstance.load(contextOptions); - const frOutputOperand = await frInstance.load(contextOptions); + const [fdOutputOperand, frOutputOperand] = await Promise.all([ + fdInstance.load(contextOptions), + frInstance.load(contextOptions), + ]); + loadTime = (performance.now() - start).toFixed(2); console.log(` done in ${loadTime} ms.`); // UI shows model building progress await ui.showProgressComponent('done', 'current', 'pending'); console.log('- Building... '); start = performance.now(); - await fdInstance.build(fdOutputOperand); - await frInstance.build(frOutputOperand); + await Promise.all([ + fdInstance.build(fdOutputOperand), + frInstance.build(frOutputOperand), + ]); buildTime = (performance.now() - start).toFixed(2); console.log(` done in ${buildTime} ms.`); } diff --git a/image_classification/mobilenet_nhwc.js b/image_classification/mobilenet_nhwc.js index 64037ea5..acc80678 100644 --- a/image_classification/mobilenet_nhwc.js +++ b/image_classification/mobilenet_nhwc.js @@ -27,14 +27,14 @@ export class MobileNetV2Nhwc { const weightsName = this.weightsUrl_ + 'Const_' + weightsSubName + '.npy'; const weights = await buildConstantByNpy(this.builder_, weightsName); const biasName = this.weightsUrl_ + 'MobilenetV2_' + biasSubName + '_bias.npy'; - const bias = await buildConstantByNpy(this.builder_, biasName); + const bias = buildConstantByNpy(this.builder_, biasName); options.inputLayout = 'nhwc'; - options.bias = bias; + options.bias = await bias; // WebNN spec drops autoPad support, compute the explicit padding instead. if (options.autoPad == 'same-upper') { options.padding = computePadding2DForAutoPad( - /* nwhc */[input.shape()[1], input.shape()[2]], + /* nwhc */[await input.shape()[1], await input.shape()[2]], /* ohwi or ihwo */[weights.shape()[1], weights.shape()[2]], options.strides, options.dilations, options.autoPad); } @@ -44,7 +44,7 @@ export class MobileNetV2Nhwc { // Implement `clip` by `clamp` of WebNN API if (this.deviceType_ == 'gpu') { return this.builder_.clamp( - this.builder_.conv2d(input, weights, options), + this.builder_.conv2d(await input, weights, options), {minValue: 0, maxValue: 6}); } else { options.activation = this.builder_.clamp({minValue: 0, maxValue: 6}); @@ -60,17 +60,32 @@ export class MobileNetV2Nhwc { dwiseOptions.autoPad = autoPad; dwiseOptions.filterLayout = 'ihwo'; - const conv1x1Relu6 = await this.buildConv_( - input, weightsNameArray[0], `${biasPrefix}_expand_Conv2D`, true, {autoPad, filterLayout: 'ohwi'}); - const dwise3x3Relu6 = await this.buildConv_( - conv1x1Relu6, weightsNameArray[1], `${biasPrefix}_depthwise_depthwise`, true, dwiseOptions); - const conv1x1Linear = await this.buildConv_( - dwise3x3Relu6, weightsNameArray[2], `${biasPrefix}_project_Conv2D`, false, {autoPad, filterLayout: 'ohwi'}); + const conv1x1Relu6 = this.buildConv_( + await input, + weightsNameArray[0], + `${biasPrefix}_expand_Conv2D`, + true, + {autoPad, filterLayout: 'ohwi'}, + ); + const dwise3x3Relu6 = this.buildConv_( + await conv1x1Relu6, + weightsNameArray[1], + `${biasPrefix}_depthwise_depthwise`, + true, + dwiseOptions, + ); + const conv1x1Linear = this.buildConv_( + await dwise3x3Relu6, + weightsNameArray[2], + `${biasPrefix}_project_Conv2D`, + false, + {autoPad, filterLayout: 'ohwi'}, + ); if (shortcut) { - return this.builder_.add(input, conv1x1Linear); + return this.builder_.add(await input, await conv1x1Linear); } - return conv1x1Linear; + return await conv1x1Linear; } async load(contextOptions) { @@ -85,53 +100,52 @@ export class MobileNetV2Nhwc { dataType: 'float32', dimensions: this.inputOptions.inputDimensions, }); - const conv0 = await this.buildConv_( + const conv0 = this.buildConv_( input, '90', 'Conv_Conv2D', true, {strides, autoPad, filterLayout}); - const conv1 = await this.buildConv_( - conv0, '238', 'expanded_conv_depthwise_depthwise', true, {autoPad, groups: 32, filterLayout: 'ihwo'}); - const conv2 = await this.buildConv_( - conv1, '167', 'expanded_conv_project_Conv2D', false, {autoPad, filterLayout}); - const bottleneck0 = await this.buildLinearBottleneck_( - conv2, ['165', '99', '73'], '1', {strides, groups: 96}, false); - const bottleneck1 = await this.buildLinearBottleneck_( + const conv1 = this.buildConv_( + await conv0, '238', 'expanded_conv_depthwise_depthwise', true, {autoPad, groups: 32, filterLayout: 'ihwo'}); + const conv2 = this.buildConv_( + await conv1, '167', 'expanded_conv_project_Conv2D', false, {autoPad, filterLayout}); + const bottleneck0 = this.buildLinearBottleneck_( + await conv2, ['165', '99', '73'], '1', {strides, groups: 96}, false); + const bottleneck1 = this.buildLinearBottleneck_( bottleneck0, ['3', '119', '115'], '2', {groups: 144}); - const bottleneck2 = await this.buildLinearBottleneck_( + const bottleneck2 = this.buildLinearBottleneck_( bottleneck1, ['255', '216', '157'], '3', {strides, groups: 144}, false); - const bottleneck3 = await this.buildLinearBottleneck_( + const bottleneck3 = this.buildLinearBottleneck_( bottleneck2, ['227', '221', '193'], '4', {groups: 192}); - const bottleneck4 = await this.buildLinearBottleneck_( + const bottleneck4 = this.buildLinearBottleneck_( bottleneck3, ['243', '102', '215'], '5', {groups: 192}); - const bottleneck5 = await this.buildLinearBottleneck_( + const bottleneck5 = this.buildLinearBottleneck_( bottleneck4, ['226', '163', '229'], '6', {strides, groups: 192}, false); - const bottleneck6 = await this.buildLinearBottleneck_( + const bottleneck6 = this.buildLinearBottleneck_( bottleneck5, ['104', '254', '143'], '7', {groups: 384}); - const bottleneck7 = await this.buildLinearBottleneck_( + const bottleneck7 = this.buildLinearBottleneck_( bottleneck6, ['25', '142', '202'], '8', {groups: 384}); - const bottleneck8 = await this.buildLinearBottleneck_( + const bottleneck8 = this.buildLinearBottleneck_( bottleneck7, ['225', '129', '98'], '9', {groups: 384}); - const bottleneck9 = await this.buildLinearBottleneck_( + const bottleneck9 = this.buildLinearBottleneck_( bottleneck8, ['169', '2', '246'], '10', {groups: 384}, false); - const bottleneck10 = await this.buildLinearBottleneck_( + const bottleneck10 = this.buildLinearBottleneck_( bottleneck9, ['162', '87', '106'], '11', {groups: 576}); - const bottleneck11 = await this.buildLinearBottleneck_( + const bottleneck11 = this.buildLinearBottleneck_( bottleneck10, ['52', '22', '40'], '12', {groups: 576}); - const bottleneck12 = await this.buildLinearBottleneck_( + const bottleneck12 = this.buildLinearBottleneck_( bottleneck11, ['114', '65', '242'], '13', {strides, groups: 576}, false); - const bottleneck13 = await this.buildLinearBottleneck_( + const bottleneck13 = this.buildLinearBottleneck_( bottleneck12, ['203', '250', '92'], '14', {groups: 960}); - const bottleneck14 = await this.buildLinearBottleneck_( + const bottleneck14 = this.buildLinearBottleneck_( bottleneck13, ['133', '130', '258'], '15', {groups: 960}); - const bottleneck15 = await this.buildLinearBottleneck_( + const bottleneck15 = this.buildLinearBottleneck_( bottleneck14, ['60', '248', '100'], '16', {groups: 960}, false); - const conv3 = await this.buildConv_( - bottleneck15, '71', 'Conv_1_Conv2D', true, {autoPad, filterLayout}); + const conv3 = this.buildConv_( + await bottleneck15, '71', 'Conv_1_Conv2D', true, {autoPad, filterLayout}); - const averagePool2d = this.builder_.averagePool2d( - conv3, {windowDimensions: [7, 7], layout: 'nhwc'}); - const conv4 = await this.buildConv_( + const averagePool2d = this.builder_.averagePool2d(await conv3, {windowDimensions: [7, 7], layout: 'nhwc'}); + const conv4 = this.buildConv_( averagePool2d, '222', 'Logits_Conv2d_1c_1x1_Conv2D', false, {autoPad, filterLayout}); - const reshape = this.builder_.reshape(conv4, [1, 1001]); - return this.builder_.softmax(reshape); + const reshape = this.builder_.reshape(await conv4, [1, 1001]); + return await this.builder_.softmax(reshape); } async build(outputOperand) { diff --git a/image_classification/resnet50v2_nchw.js b/image_classification/resnet50v2_nchw.js index 1569b41f..706f943d 100644 --- a/image_classification/resnet50v2_nchw.js +++ b/image_classification/resnet50v2_nchw.js @@ -30,8 +30,8 @@ export class ResNet50V2Nchw { prefix = this.weightsUrl_ + 'resnetv24_conv' + name; } const weightName = prefix + '_weight.npy'; - const weight = await buildConstantByNpy(this.builder_, weightName); - return this.builder_.conv2d(input, weight, options); + const weight = buildConstantByNpy(this.builder_, weightName); + return this.builder_.conv2d(await input, await weight, options); } async buildBatchNorm_(input, name, stageName, relu = true) { @@ -46,26 +46,31 @@ export class ResNet50V2Nchw { const biasName = prefix + '_beta.npy'; const meanName = prefix + '_running_mean.npy'; const varName = prefix + '_running_var.npy'; - const scale = await buildConstantByNpy(this.builder_, scaleName); - const bias = await buildConstantByNpy(this.builder_, biasName); - const mean = await buildConstantByNpy(this.builder_, meanName); - const variance = await buildConstantByNpy(this.builder_, varName); - const options = {scale: scale, bias: bias}; + const scale = buildConstantByNpy(this.builder_, scaleName); + const bias = buildConstantByNpy(this.builder_, biasName); + const mean = buildConstantByNpy(this.builder_, meanName); + const variance = buildConstantByNpy(this.builder_, varName); + const options = {scale: await scale, bias: await bias}; if (relu) { options.activation = this.builder_.relu(); } - return this.builder_.batchNormalization(input, mean, variance, options); + return this.builder_.batchNormalization( + await input, + await mean, + await variance, + options, + ); } async buildGemm_(input, name) { const prefix = this.weightsUrl_ + 'resnetv24_dense' + name; const weightName = prefix + '_weight.npy'; - const weight = await buildConstantByNpy(this.builder_, weightName); + const weight = buildConstantByNpy(this.builder_, weightName); const biasName = prefix + '_bias.npy'; - const bias = await buildConstantByNpy(this.builder_, biasName); + const bias = buildConstantByNpy(this.builder_, biasName); const options = - {c: this.builder_.reshape(bias, [1, 1000]), bTranspose: true}; - return this.builder_.gemm(input, weight, options); + {c: this.builder_.reshape(await bias, [1, 1000]), bTranspose: true}; + return this.builder_.gemm(await input, await weight, options); } async buildBottlenectV2_( @@ -76,20 +81,20 @@ export class ResNet50V2Nchw { if (downsample) { strides = [stride, stride]; } - const bn1 = await this.buildBatchNorm_(input, nameIndices[0], stageName); - const conv1 = await this.buildConv_(bn1, nameIndices[1], stageName); - const bn2 = await this.buildBatchNorm_( + const bn1 = this.buildBatchNorm_(input, nameIndices[0], stageName); + const conv1 = this.buildConv_(bn1, nameIndices[1], stageName); + const bn2 = this.buildBatchNorm_( conv1, parseInt(nameIndices[0]) + 1, stageName); - const conv2 = await this.buildConv_( + const conv2 = this.buildConv_( bn2, nameIndices[2], stageName, {padding: [1, 1, 1, 1], strides}); - const bn3 = await this.buildBatchNorm_( + const bn3 = this.buildBatchNorm_( conv2, parseInt(nameIndices[0]) + 2, stageName); - const conv3 = await this.buildConv_(bn3, nameIndices[3], stageName); + const conv3 = this.buildConv_(bn3, nameIndices[3], stageName); if (downsample) { - residual = await this.buildConv_( + residual = this.buildConv_( bn1, parseInt(nameIndices[0]) + 3, stageName, {strides}); } - return this.builder_.add(conv3, residual); + return this.builder_.add(await conv3, await residual); } async load(contextOptions) { @@ -100,76 +105,73 @@ export class ResNet50V2Nchw { dataType: 'float32', dimensions: this.inputOptions.inputDimensions, }); - const bn1 = await this.buildBatchNorm_(data, '0', '', false); - const conv0 = await this.buildConv_( + const bn1 = this.buildBatchNorm_(data, '0', '', false); + const conv0 = this.buildConv_( bn1, '0', '', {padding: [3, 3, 3, 3], strides: [2, 2]}); - const bn2 = await this.buildBatchNorm_(conv0, '1', ''); - const pool1 = await this.builder_.maxPool2d(bn2, + const bn2 = this.buildBatchNorm_(conv0, '1', ''); + const pool1 = this.builder_.maxPool2d(await bn2, {windowDimensions: [3, 3], padding: [1, 1, 1, 1], strides: [2, 2]}); // Stage 1 - const bottleneck1 = await this.buildBottlenectV2_( + const bottleneck1 = this.buildBottlenectV2_( pool1, '1', ['0', '0', '1', '2'], true); - const bottleneck2 = await this.buildBottlenectV2_( + const bottleneck2 = this.buildBottlenectV2_( bottleneck1, '1', ['3', '4', '5', '6']); - const bottleneck3 = await this.buildBottlenectV2_( + const bottleneck3 = this.buildBottlenectV2_( bottleneck2, '1', ['6', '7', '8', '9']); // Stage 2 - const bottleneck4 = await this.buildBottlenectV2_( + const bottleneck4 = this.buildBottlenectV2_( bottleneck3, '2', ['0', '0', '1', '2'], true, 2); - const bottleneck5 = await this.buildBottlenectV2_( + const bottleneck5 = this.buildBottlenectV2_( bottleneck4, '2', ['3', '4', '5', '6']); - const bottleneck6 = await this.buildBottlenectV2_( + const bottleneck6 = this.buildBottlenectV2_( bottleneck5, '2', ['6', '7', '8', '9']); - const bottleneck7 = await this.buildBottlenectV2_( + const bottleneck7 = this.buildBottlenectV2_( bottleneck6, '2', ['9', '10', '11', '12']); // Stage 3 - const bottleneck8 = await this.buildBottlenectV2_( + const bottleneck8 = this.buildBottlenectV2_( bottleneck7, '3', ['0', '0', '1', '2'], true, 2); - const bottleneck9 = await this.buildBottlenectV2_( + const bottleneck9 = this.buildBottlenectV2_( bottleneck8, '3', ['3', '4', '5', '6']); - const bottleneck10 = await this.buildBottlenectV2_( + const bottleneck10 = this.buildBottlenectV2_( bottleneck9, '3', ['6', '7', '8', '9']); - const bottleneck11 = await this.buildBottlenectV2_( + const bottleneck11 = this.buildBottlenectV2_( bottleneck10, '3', ['9', '10', '11', '12']); - const bottleneck12 = await this.buildBottlenectV2_( + const bottleneck12 = this.buildBottlenectV2_( bottleneck11, '3', ['12', '13', '14', '15']); - const bottleneck13 = await this.buildBottlenectV2_( + const bottleneck13 = this.buildBottlenectV2_( bottleneck12, '3', ['15', '16', '17', '18']); // Stage 4 - const bottleneck14 = await this.buildBottlenectV2_( + const bottleneck14 = this.buildBottlenectV2_( bottleneck13, '4', ['0', '0', '1', '2'], true, 2); - const bottleneck15 = await this.buildBottlenectV2_( + const bottleneck15 = this.buildBottlenectV2_( bottleneck14, '4', ['3', '4', '5', '6']); - const bottleneck16 = await this.buildBottlenectV2_( + const bottleneck16 = this.buildBottlenectV2_( bottleneck15, '4', ['6', '7', '8', '9']); - const bn3 = await this.buildBatchNorm_(bottleneck16, '2', ''); - const pool2 = await this.builder_.averagePool2d(bn3); - const reshape = this.builder_.reshape(pool2, [1, 2048]); - const gemm = await this.buildGemm_(reshape, '0'); - return this.builder_.softmax(gemm); + const bn3 = this.buildBatchNorm_(bottleneck16, '2', ''); + const pool2 = this.builder_.averagePool2d(await bn3); + const reshape = this.builder_.reshape(await pool2, [1, 2048]); + const gemm = this.buildGemm_(await reshape, '0'); + return this.builder_.softmax(await gemm); } async build(outputOperand) { - this.graph_ = await this.builder_.build({'output': outputOperand}); + this.graph_ = this.builder_.build({'output': outputOperand}); } // Release the constant tensors of a model - dispose() { - // dispose() is only available in webnn-polyfill - if (this.graph_ !== null && 'dispose' in this.graph_) { - this.graph_.dispose(); - } - } - async compute(inputBuffer, outputBuffer) { const inputs = {'input': inputBuffer}; const outputs = {'output': outputBuffer}; - const results = await this.context_.compute(this.graph_, inputs, outputs); + const results = await this.context_.compute( + await this.graph_, + inputs, + outputs, + ); return results; } } diff --git a/image_classification/resnet50v2_nhwc.js b/image_classification/resnet50v2_nhwc.js index 2cf264ca..4fddf166 100644 --- a/image_classification/resnet50v2_nhwc.js +++ b/image_classification/resnet50v2_nhwc.js @@ -44,10 +44,10 @@ export class ResNet50V2Nhwc { const weightsName = prefix + '_weights.npy'; const weights = await buildConstantByNpy(this.builder_, weightsName); const biasName = prefix + '_Conv2D_bias.npy'; - const bias = await buildConstantByNpy(this.builder_, biasName); + const bias = buildConstantByNpy(this.builder_, biasName); options.inputLayout = layout; options.filterLayout = 'ohwi'; - options.bias = bias; + options.bias = await bias; if (relu) { options.activation = this.builder_.relu(); } @@ -55,11 +55,11 @@ export class ResNet50V2Nhwc { if (options.autoPad == 'same-upper') { options.padding = computePadding2DForAutoPad( - /* nwhc */[input.shape()[1], input.shape()[2]], + /* nwhc */[await input.shape()[1], await input.shape()[2]], /* ohwi */[weights.shape()[1], weights.shape()[2]], options.strides, options.dilations, options.autoPad); } - return this.builder_.conv2d(input, weights, options); + return this.builder_.conv2d(await input, weights, options); } async buildFusedBatchNorm_(input, nameIndices) { @@ -71,37 +71,52 @@ export class ResNet50V2Nhwc { `block${nameIndices[0]}_unit_${nameIndices[1]}_bottleneck_v2_preact`; } const mulParamName = prefix + '_FusedBatchNorm_mul_0_param.npy'; - const mulParam = await buildConstantByNpy(this.builder_, mulParamName); + const mulParam = buildConstantByNpy(this.builder_, mulParamName); const addParamName = prefix + '_FusedBatchNorm_add_param.npy'; - const addParam = await buildConstantByNpy(this.builder_, addParamName); + const addParam = buildConstantByNpy(this.builder_, addParamName); return this.builder_.relu( - this.builder_.add(this.builder_.mul(input, mulParam), addParam)); + this.builder_.add( + this.builder_.mul(await input, await mulParam), + await addParam, + ), + ); } async buildBottleneckV2_( input, nameIndices, downsample = false, shortcut = true) { - let residual = input; + let residual = await input; - const fusedBn = await this.buildFusedBatchNorm_(input, nameIndices); - const conv1 = await this.buildConv_( - fusedBn, nameIndices.concat(['1']), {autoPad}); + const fusedBn = this.buildFusedBatchNorm_(await input, nameIndices); + const conv1 = this.buildConv_( + await fusedBn, nameIndices.concat(['1']), {autoPad}); let conv2; if (downsample) { - residual = await this.buildConv_( - fusedBn, nameIndices.concat(['shortcut']), {autoPad}, false); + residual = this.buildConv_( + await fusedBn, nameIndices.concat(['shortcut']), {autoPad}, false); } if (!downsample && shortcut) { residual = this.builder_.maxPool2d( - input, {windowDimensions: [2, 2], strides, layout, autoPad}); - conv2 = await this.buildConv_( - conv1, nameIndices.concat(['2']), {strides, padding: [1, 1, 1, 1]}); + await input, { + windowDimensions: [2, 2], + strides, + layout, + autoPad, + }, + ); + conv2 = this.buildConv_( + await conv1, nameIndices.concat(['2']), { + strides, + padding: [1, 1, 1, 1], + }, + ); } else { - conv2 = await this.buildConv_( - conv1, nameIndices.concat(['2']), {autoPad}); + conv2 = this.buildConv_( + await conv1, nameIndices.concat(['2']), {autoPad}, + ); } - const conv3 = await this.buildConv_( - conv2, nameIndices.concat(['3']), {autoPad}, false); - return this.builder_.add(conv3, residual); + const conv3 = this.buildConv_( + await conv2, nameIndices.concat(['3']), {autoPad}, false); + return this.builder_.add(await conv3, await residual); } async load(contextOptions) { @@ -122,72 +137,69 @@ export class ResNet50V2Nhwc { windowDimensions, strides, /* dilations */ undefined, 'same-upper')}); // Block 1 - const bottleneck1 = await this.buildBottleneckV2_(pool, ['1', '1'], true); - const bottleneck2 = await this.buildBottleneckV2_( + const bottleneck1 = this.buildBottleneckV2_(pool, ['1', '1'], true); + const bottleneck2 = this.buildBottleneckV2_( bottleneck1, ['1', '2'], false, false); - const bottleneck3 = await this.buildBottleneckV2_( + const bottleneck3 = this.buildBottleneckV2_( bottleneck2, ['1', '3']); // Block 2 - const bottleneck4 = await this.buildBottleneckV2_( + const bottleneck4 = this.buildBottleneckV2_( bottleneck3, ['2', '1'], true); - const bottleneck5 = await this.buildBottleneckV2_( + const bottleneck5 = this.buildBottleneckV2_( bottleneck4, ['2', '2'], false, false); - const bottleneck6 = await this.buildBottleneckV2_( + const bottleneck6 = this.buildBottleneckV2_( bottleneck5, ['2', '3'], false, false); - const bottleneck7 = await this.buildBottleneckV2_( + const bottleneck7 = this.buildBottleneckV2_( bottleneck6, ['2', '4']); // Block 3 - const bottleneck8 = await this.buildBottleneckV2_( + const bottleneck8 = this.buildBottleneckV2_( bottleneck7, ['3', '1'], true); const loop = async (node, num) => { if (num > 5) { return node; } else { - const newNode = await this.buildBottleneckV2_( + const newNode = this.buildBottleneckV2_( node, ['3', num.toString()], false, false); num++; return loop(newNode, num); } }; - const bottleneck9 = await loop(bottleneck8, 2); - const bottleneck10 = await this.buildBottleneckV2_( + const bottleneck9 = loop(bottleneck8, 2); + const bottleneck10 = this.buildBottleneckV2_( bottleneck9, ['3', '6']); // Block 4 - const bottleneck11 = await this.buildBottleneckV2_( + const bottleneck11 = this.buildBottleneckV2_( bottleneck10, ['4', '1'], true); - const bottleneck12 = await this.buildBottleneckV2_( + const bottleneck12 = this.buildBottleneckV2_( bottleneck11, ['4', '2'], false, false); - const bottleneck13 = await this.buildBottleneckV2_( + const bottleneck13 = this.buildBottleneckV2_( bottleneck12, ['4', '3'], false, false); const fusedBn = - await this.buildFusedBatchNorm_(bottleneck13, ['postnorm']); - const mean = this.builder_.averagePool2d(fusedBn, {layout}); - const conv2 = await this.buildConv_( + this.buildFusedBatchNorm_(bottleneck13, ['postnorm']); + const mean = this.builder_.averagePool2d(await fusedBn, {layout}); + const conv2 = this.buildConv_( mean, ['', '', 'logits'], {autoPad}, false); - const reshape = this.builder_.reshape(conv2, [1, 1001]); + const reshape = this.builder_.reshape(await conv2, [1, 1001]); return this.builder_.softmax(reshape); } async build(outputOperand) { - this.graph_ = await this.builder_.build({'output': outputOperand}); + this.graph_ = this.builder_.build({'output': outputOperand}); } // Release the constant tensors of a model - dispose() { - // dispose() is only available in webnn-polyfill - if (this.graph_ !== null && 'dispose' in this.graph_) { - this.graph_.dispose(); - } - } - async compute(inputBuffer, outputBuffer) { const inputs = {'input': inputBuffer}; const outputs = {'output': outputBuffer}; - const results = await this.context_.compute(this.graph_, inputs, outputs); + const results = await this.context_.compute( + await this.graph_, + inputs, + outputs, + ); return results; } } diff --git a/image_classification/squeezenet_nchw.js b/image_classification/squeezenet_nchw.js index b49b14d3..e639816f 100644 --- a/image_classification/squeezenet_nchw.js +++ b/image_classification/squeezenet_nchw.js @@ -24,20 +24,20 @@ export class SqueezeNetNchw { async buildConv_(input, name, options = {}) { const prefix = this.weightsUrl_ + 'squeezenet0_' + name; const weightsName = prefix + '_weight.npy'; - const weights = await buildConstantByNpy(this.builder_, weightsName); + const weights = buildConstantByNpy(this.builder_, weightsName); const biasName = prefix + '_bias.npy'; - const bias = await buildConstantByNpy(this.builder_, biasName); - options.bias = bias; + const bias = buildConstantByNpy(this.builder_, biasName); + options.bias = await bias; options.activation = this.builder_.relu(); - return this.builder_.conv2d(input, weights, options); + return this.builder_.conv2d(await input, await weights, options); } async buildFire_(input, convName, conv1x1Name, conv3x3Name) { - const conv = await this.buildConv_(input, convName); - const conv1x1 = await this.buildConv_(conv, conv1x1Name); - const conv3x3 = await this.buildConv_( + const conv = this.buildConv_(input, convName); + const conv1x1 = this.buildConv_(conv, conv1x1Name); + const conv3x3 = this.buildConv_( conv, conv3x3Name, {padding: [1, 1, 1, 1]}); - return this.builder_.concat([conv1x1, conv3x3], 1); + return this.builder_.concat([await conv1x1, await conv3x3], 1); } async load(contextOptions) { @@ -48,24 +48,24 @@ export class SqueezeNetNchw { dataType: 'float32', dimensions: this.inputOptions.inputDimensions, }); - const conv0 = await this.buildConv_(data, 'conv0', {strides: [2, 2]}); + const conv0 = this.buildConv_(data, 'conv0', {strides: [2, 2]}); const pool0 = this.builder_.maxPool2d( - conv0, {windowDimensions: [3, 3], strides: [2, 2]}); - const fire0 = await this.buildFire_(pool0, 'conv1', 'conv2', 'conv3'); - const fire1 = await this.buildFire_(fire0, 'conv4', 'conv5', 'conv6'); + await conv0, {windowDimensions: [3, 3], strides: [2, 2]}); + const fire0 = this.buildFire_(pool0, 'conv1', 'conv2', 'conv3'); + const fire1 = this.buildFire_(fire0, 'conv4', 'conv5', 'conv6'); const pool1 = this.builder_.maxPool2d( - fire1, {windowDimensions: [3, 3], strides: [2, 2]}); - const fire2 = await this.buildFire_(pool1, 'conv7', 'conv8', 'conv9'); - const fire3 = await this.buildFire_(fire2, 'conv10', 'conv11', 'conv12'); + await fire1, {windowDimensions: [3, 3], strides: [2, 2]}); + const fire2 = this.buildFire_(pool1, 'conv7', 'conv8', 'conv9'); + const fire3 = this.buildFire_(fire2, 'conv10', 'conv11', 'conv12'); const pool2 = this.builder_.maxPool2d( - fire3, {windowDimensions: [3, 3], strides: [2, 2]}); - const fire4 = await this.buildFire_(pool2, 'conv13', 'conv14', 'conv15'); - const fire5 = await this.buildFire_(fire4, 'conv16', 'conv17', 'conv18'); - const fire6 = await this.buildFire_(fire5, 'conv19', 'conv20', 'conv21'); - const fire7 = await this.buildFire_(fire6, 'conv22', 'conv23', 'conv24'); - const conv25 = await this.buildConv_(fire7, 'conv25'); + await fire3, {windowDimensions: [3, 3], strides: [2, 2]}); + const fire4 = this.buildFire_(pool2, 'conv13', 'conv14', 'conv15'); + const fire5 = this.buildFire_(fire4, 'conv16', 'conv17', 'conv18'); + const fire6 = this.buildFire_(fire5, 'conv19', 'conv20', 'conv21'); + const fire7 = this.buildFire_(fire6, 'conv22', 'conv23', 'conv24'); + const conv25 = this.buildConv_(fire7, 'conv25'); const pool3 = this.builder_.averagePool2d( - conv25, {windowDimensions: [13, 13], strides: [13, 13]}); + await conv25, {windowDimensions: [13, 13], strides: [13, 13]}); const reshape0 = this.builder_.reshape(pool3, [1, 1000]); return this.builder_.softmax(reshape0); } diff --git a/image_classification/squeezenet_nhwc.js b/image_classification/squeezenet_nhwc.js index 21a8e95d..2746bd15 100644 --- a/image_classification/squeezenet_nhwc.js +++ b/image_classification/squeezenet_nhwc.js @@ -25,28 +25,28 @@ export class SqueezeNetNhwc { const weightsName = prefix + '_kernel.npy'; const weights = await buildConstantByNpy(this.builder_, weightsName); const biasName = prefix + '_Conv2D_bias.npy'; - const bias = await buildConstantByNpy(this.builder_, biasName); + const bias = buildConstantByNpy(this.builder_, biasName); options.inputLayout = 'nhwc'; options.filterLayout = 'ohwi'; - options.bias = bias; + options.bias = await bias; options.activation = this.builder_.relu(); // WebNN spec drops autoPad support, compute the explicit padding instead. if (options.autoPad == 'same-upper') { options.padding = computePadding2DForAutoPad( - /* nwhc */[input.shape()[1], input.shape()[2]], + /* nwhc */[await input.shape()[1], await input.shape()[2]], /* ohwi */[weights.shape()[1], weights.shape()[2]], options.strides, options.dilations, options.autoPad); } - return this.builder_.conv2d(input, weights, options); + return this.builder_.conv2d(await input, weights, options); } async buildFire_(input, name) { - const convSqueeze = await this.buildConv_(input, name + '_squeeze'); - const convE1x1 = await this.buildConv_(convSqueeze, name + '_e1x1'); - const convE3x3 = await this.buildConv_( + const convSqueeze = this.buildConv_(input, name + '_squeeze'); + const convE1x1 = this.buildConv_(convSqueeze, name + '_e1x1'); + const convE3x3 = this.buildConv_( convSqueeze, name + '_e3x3', {padding: [1, 1, 1, 1]}); - return this.builder_.concat([convE1x1, convE3x3], 3); + return this.builder_.concat([await convE1x1, await convE3x3], 3); } async load(contextOptions) { @@ -59,25 +59,25 @@ export class SqueezeNetNhwc { dataType: 'float32', dimensions: this.inputOptions.inputDimensions, }); - const conv1 = await this.buildConv_( + const conv1 = this.buildConv_( placeholder, 'conv1', {strides, autoPad: 'same-upper'}); const maxpool1 = this.builder_.maxPool2d( - conv1, {windowDimensions: [3, 3], strides, layout}); - const fire2 = await this.buildFire_(maxpool1, 'fire2'); - const fire3 = await this.buildFire_(fire2, 'fire3'); - const fire4 = await this.buildFire_(fire3, 'fire4'); + await conv1, {windowDimensions: [3, 3], strides, layout}); + const fire2 = this.buildFire_(maxpool1, 'fire2'); + const fire3 = this.buildFire_(fire2, 'fire3'); + const fire4 = this.buildFire_(fire3, 'fire4'); const maxpool4 = this.builder_.maxPool2d( - fire4, {windowDimensions: [3, 3], strides, layout}); - const fire5 = await this.buildFire_(maxpool4, 'fire5'); - const fire6 = await this.buildFire_(fire5, 'fire6'); - const fire7 = await this.buildFire_(fire6, 'fire7'); - const fire8 = await this.buildFire_(fire7, 'fire8'); + await fire4, {windowDimensions: [3, 3], strides, layout}); + const fire5 = this.buildFire_(maxpool4, 'fire5'); + const fire6 = this.buildFire_(fire5, 'fire6'); + const fire7 = this.buildFire_(fire6, 'fire7'); + const fire8 = this.buildFire_(fire7, 'fire8'); const maxpool8 = this.builder_.maxPool2d( - fire8, {windowDimensions: [3, 3], strides, layout}); - const fire9 = await this.buildFire_(maxpool8, 'fire9'); - const conv10 = await this.buildConv_(fire9, 'conv10'); + await fire8, {windowDimensions: [3, 3], strides, layout}); + const fire9 = this.buildFire_(maxpool8, 'fire9'); + const conv10 = this.buildConv_(fire9, 'conv10'); const averagePool2d = this.builder_.averagePool2d( - conv10, {windowDimensions: [13, 13], layout}); + await conv10, {windowDimensions: [13, 13], layout}); const reshape = this.builder_.reshape(averagePool2d, [1, 1001]); return this.builder_.softmax(reshape); } diff --git a/semantic_segmentation/deeplabv3_mnv2_nchw.js b/semantic_segmentation/deeplabv3_mnv2_nchw.js index 9edd1ea3..06ae8f08 100644 --- a/semantic_segmentation/deeplabv3_mnv2_nchw.js +++ b/semantic_segmentation/deeplabv3_mnv2_nchw.js @@ -41,17 +41,17 @@ export class DeepLabV3MNV2Nchw { biasName = biasPrefix + '_biases.npy'; } - const weights = await buildConstantByNpy(this.builder_, weightsName); - const bias = await buildConstantByNpy(this.builder_, biasName); + const weights = buildConstantByNpy(this.builder_, weightsName); + const bias = buildConstantByNpy(this.builder_, biasName); - options.bias = bias; + options.bias = await bias; if (activation === 'relu6') { // TODO: Set clamp activation to options once it's supported in // WebNN DML backend. // Implement `clip` by `clamp` of WebNN API if (this.deviceType_ == 'gpu') { return this.builder_.clamp( - this.builder_.conv2d(input, weights, options), + this.builder_.conv2d(await input, await weights, options), {minValue: 0, maxValue: 6}); } else { options.activation = this.builder_.clamp({minValue: 0, maxValue: 6}); @@ -61,7 +61,7 @@ export class DeepLabV3MNV2Nchw { } else { options.activation = undefined; } - return this.builder_.conv2d(input, weights, options); + return this.builder_.conv2d(await input, await weights, options); } async buildLinearBottleneck_(input, nameArray, dwiseOptions, shortcut = true) { @@ -72,21 +72,21 @@ export class DeepLabV3MNV2Nchw { if (Number.parseInt(nameArray[0]) > 6) { dwBiasSuffix = 'BatchNorm_FusedBatchNorm'; } - const conv1x1Relu6 = await this.buildConv_( + const conv1x1Relu6 = this.buildConv_( input, [`${biasPrefix}_expand_Conv2D`, dwBiasSuffix, nameArray[1]]); - const dwise3x3Relu6 = await this.buildConv_( + const dwise3x3Relu6 = this.buildConv_( conv1x1Relu6, [`${biasPrefix}_depthwise`, dwBiasSuffix, nameArray[2]], 'relu6', dwiseOptions); - const conv1x1Linear = await this.buildConv_( + const conv1x1Linear = this.buildConv_( dwise3x3Relu6, [`${biasPrefix}_project_Conv2D`, dwBiasSuffix, nameArray[3]], 'none'); if (shortcut) { - return this.builder_.add(input, conv1x1Linear); + return this.builder_.add(await input, await conv1x1Linear); } return conv1x1Linear; } @@ -102,58 +102,58 @@ export class DeepLabV3MNV2Nchw { dataType: 'float32', dimensions: this.inputOptions.inputDimensions, }); - const conv0 = await this.buildConv_( + const conv0 = this.buildConv_( input, ['MobilenetV2_Conv_Conv2D', '', '551'], 'relu6', {strides, padding: [1, 1, 1, 1]}); - const conv1 = await this.buildConv_( + const conv1 = this.buildConv_( conv0, ['MobilenetV2_expanded_conv_depthwise_depthwise', '', '543'], 'relu6', {padding: [1, 1, 1, 1], groups: 32}); - const conv2 = await this.buildConv_( + const conv2 = this.buildConv_( conv1, ['MobilenetV2_expanded_conv_project_Conv2D', '', '511'], 'none'); - const bottleneck0 = await this.buildLinearBottleneck_( + const bottleneck0 = this.buildLinearBottleneck_( conv2, ['1', '537', '494', '534'], {strides, padding: [1, 1, 1, 1], groups: 96}, false); - const bottleneck1 = await this.buildLinearBottleneck_( + const bottleneck1 = this.buildLinearBottleneck_( bottleneck0, ['2', '447', '555', '523'], {padding: [1, 1, 1, 1], groups: 144}); - const bottleneck2 = await this.buildLinearBottleneck_( + const bottleneck2 = this.buildLinearBottleneck_( bottleneck1, ['3', '520', '562', '542'], {strides, padding: [1, 1, 1, 1], groups: 144}, false); - const bottleneck3 = await this.buildLinearBottleneck_( + const bottleneck3 = this.buildLinearBottleneck_( bottleneck2, ['4', '503', '505', '489'], {padding: [1, 1, 1, 1], groups: 192}); - const bottleneck4 = await this.buildLinearBottleneck_( + const bottleneck4 = this.buildLinearBottleneck_( bottleneck3, ['5', '446', '530', '522'], {padding: [1, 1, 1, 1], groups: 192}); - const bottleneck5 = await this.buildLinearBottleneck_( + const bottleneck5 = this.buildLinearBottleneck_( bottleneck4, ['6', '491', '561', '538'], {padding: [1, 1, 1, 1], groups: 192}, false); - const bottleneck6 = await this.buildLinearBottleneck_( + const bottleneck6 = this.buildLinearBottleneck_( bottleneck5, ['7', '487', '560', '478'], {padding: [2, 2, 2, 2], groups: 384, dilations: [2, 2]}); - const bottleneck7 = await this.buildLinearBottleneck_( + const bottleneck7 = this.buildLinearBottleneck_( bottleneck6, ['8', '467', '536', '455'], {padding: [2, 2, 2, 2], groups: 384, dilations: [2, 2]}); - const bottleneck8 = await this.buildLinearBottleneck_( + const bottleneck8 = this.buildLinearBottleneck_( bottleneck7, ['9', '474', '524', '558'], {padding: [2, 2, 2, 2], groups: 384, dilations: [2, 2]}); - const bottleneck9 = await this.buildLinearBottleneck_( + const bottleneck9 = this.buildLinearBottleneck_( bottleneck8, ['10', '465', '556', '462'], {padding: [2, 2, 2, 2], groups: 384, dilations: [2, 2]}, false); - const bottleneck10 = await this.buildLinearBottleneck_( + const bottleneck10 = this.buildLinearBottleneck_( bottleneck9, ['11', '453', '532', '450'], {padding: [2, 2, 2, 2], groups: 576, dilations: [2, 2]}); - const bottleneck11 = await this.buildLinearBottleneck_( + const bottleneck11 = this.buildLinearBottleneck_( bottleneck10, ['12', '441', '554', '517'], {padding: [2, 2, 2, 2], groups: 576, dilations: [2, 2]}); - const bottleneck12 = await this.buildLinearBottleneck_( + const bottleneck12 = this.buildLinearBottleneck_( bottleneck11, ['13', '544', '509', '479'], {padding: [2, 2, 2, 2], groups: 576, dilations: [2, 2]}, false); - const bottleneck13 = await this.buildLinearBottleneck_( + const bottleneck13 = this.buildLinearBottleneck_( bottleneck12, ['14', '482', '552', '512'], {padding: [4, 4, 4, 4], groups: 960, dilations: [4, 4]}); - const bottleneck14 = await this.buildLinearBottleneck_( + const bottleneck14 = this.buildLinearBottleneck_( bottleneck13, ['15', '475', '495', '563'], {padding: [4, 4, 4, 4], groups: 960, dilations: [4, 4]}); - const bottleneck15 = await this.buildLinearBottleneck_( + const bottleneck15 = this.buildLinearBottleneck_( bottleneck14, ['16', '500', '459', '539'], {padding: [4, 4, 4, 4], groups: 960, dilations: [4, 4]}, false); - const conv3 = await this.buildConv_(bottleneck15, ['aspp0_Conv2D', '', '553'], 'relu'); + const conv3 = this.buildConv_(bottleneck15, ['aspp0_Conv2D', '', '553'], 'relu'); const averagePool2d = this.builder_.averagePool2d( - bottleneck15, {windowDimensions: [65, 65], layout: 'nchw'}); - const conv4 = await this.buildConv_(averagePool2d, ['image_pooling_Conv2D', '', '546'], 'relu'); + await bottleneck15, {windowDimensions: [65, 65], layout: 'nchw'}); + const conv4 = this.buildConv_(averagePool2d, ['image_pooling_Conv2D', '', '546'], 'relu'); const resample0 = this.builder_.resample2d( - conv4, {sizes: [65, 65], mode: 'linear'}); - const concat = this.builder_.concat([resample0, conv3], 1); + await conv4, {sizes: [65, 65], mode: 'linear'}); + const concat = this.builder_.concat([await resample0, await conv3], 1); - const conv5 = await this.buildConv_(concat, ['concat_projection_Conv2D', '', '502'], 'relu'); - const conv6 = await this.buildConv_(conv5, ['logits_semantic', '', '541'], 'none'); + const conv5 = this.buildConv_(concat, ['concat_projection_Conv2D', '', '502'], 'relu'); + const conv6 = this.buildConv_(conv5, ['logits_semantic', '', '541'], 'none'); const resample1 = this.builder_.resample2d( - conv6, {sizes: [65, 65], mode: 'linear'}); + await conv6, {sizes: [65, 65], mode: 'linear'}); return this.builder_.resample2d( resample1, {sizes: [513, 513], mode: 'linear'}); }