Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Demo reuse code for WebNN op tests #442

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
17 changes: 17 additions & 0 deletions webnn/clamp.https.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// META: title=test WebNN API clamp operation
// META: global=window,dedicatedworker
// META: script=./resources/utils.js
// META: timeout=long

'use strict';

// https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-clamp

const computeClamp = (builder, resources) => {
// MLOperand clamp(MLOperand x, optional MLClampOptions options = {});
// use 'x' for input operand name
const [inputOperand] = createInputOperands(builder, resources, ['x']);
return builder.clamp(inputOperand, resources.options);
};

testWebNNOperation('clamp', '/webnn/resources/test_data/clamp.json', computeClamp);
Copy link
Owner Author

@BruceDai BruceDai Nov 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I intend to use the following solution for next adding tests converted from native tests, like NNAPI, DML.
@huningxin, any suggestions, thanks.

Solution:

testWebNNOperation('clamp', '/webnn/resources/test_data/clamp.json', computeClamp);
testWebNNOperation('clamp', '/webnn/resources/test_data/clamp_nnapi.json', computeClamp);
testWebNNOperation('clamp', '/webnn/resources/test_data/clamp_dml.json', computeClamp);

For tests of elementwise binary ops,

// in elementwise_binary.https.any.js
const computeBinary = (builder, resources, name) => { 
  // MLOperand add(MLOperand a, MLOperand b);
  // MLOperand sub(MLOperand a, MLOperand b);
  // MLOperand mul(MLOperand a, MLOperand b);
  // MLOperand div(MLOperand a, MLOperand b);
  // MLOperand max(MLOperand a, MLOperand b);
  // MLOperand min(MLOperand a, MLOperand b);
  // MLOperand pow(MLOperand a, MLOperand b);
  // use 'a' and 'b' for input operands name
  const [inputOperandA, inputOperandB] = createInputOperands(builder, resources, ['a', 'b']);
  return builder[name](inputOperandA, inputOperandB);
};

testWebNNOperation('add', '/webnn/resources/test_data/add.json', computeBinary);
testWebNNOperation('sub', '/webnn/resources/test_data/sub.json', computeBinary);
testWebNNOperation('mul', '/webnn/resources/test_data/mul.json', computeBinary);
testWebNNOperation('div', '/webnn/resources/test_data/div.json', computeBinary);
testWebNNOperation('max', '/webnn/resources/test_data/max.json', computeBinary);
testWebNNOperation('min', '/webnn/resources/test_data/min.json', computeBinary);
testWebNNOperation('pow', '/webnn/resources/test_data/pow.json', computeBinary);

Copy link
Owner Author

@BruceDai BruceDai Nov 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we merged later converted NNAPI/DML tests into <operation-name>.json, not sperate tests by files (disadvantage: the file size of all-in-one <operation-name>.json would be larger),we maybe optimize
testWebNNOperation()
to
testWebNNOperation([op-name1, op-name2...], func), like
testWebNNOperation(['add', 'sub', 'mul', 'div', 'max', 'min', 'pow'], computeBinary)

,any suggestions? Thanks.

19 changes: 19 additions & 0 deletions webnn/concat.https.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// META: title=test WebNN API concat operation
// META: global=window,dedicatedworker
// META: script=./resources/utils.js
// META: timeout=long

'use strict';

// https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-concat

const computeConcat = (builder, resources) => {
// MLOperand concat(sequence<MLOperand> inputs, long axis);
const inputOperands = [];
for (let input of resources.inputs) {
inputOperands.push(builder.input(input.name, {type: resources.type, dimensions: input.shape}));
}
return builder.concat(inputOperands, resources.axis);
};

testWebNNOperation('concat', '/webnn/resources/test_data/concat.json', computeConcat);
45 changes: 45 additions & 0 deletions webnn/gemm.https.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// META: title=test WebNN API gemm operation
// META: global=window,dedicatedworker
// META: script=./resources/utils.js
// META: timeout=long

'use strict';

// https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-gemm

const computeGemm = (builder, resources) => {
// MLOperand gemm(MLOperand a, MLOperand b, optional MLGemmOptions options = {});
// use 'a' and 'b' for input operands name
const [inputOperandA, inputOperandB] = createInputOperands(builder, resources, ['a', 'b']);
const operandType = resources.type;
const TestTypedArray = TypedArrayDict[operandType];
const options = resources.options;
const gemmOptions = {};
if (options !== undefined) {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needs to process options of test json file to pass to gemm(MLOperand a, MLOperand b, optional MLGemmOptions options = {}) when options.c is not a scalar, need use new variable gemmOptions to save for different builder/context

 context = navigator.ml.createContextSync({deviceType});
 //  or 
 // context = await navigator.ml.createContext({deviceType});
 builder = new MLGraphBuilder(context);

if (options.c !== undefined) {
if (typeof options.c === 'number') {
// scalar
gemmOptions.c = new TestTypedArray([options.c])[0];
} else {
gemmOptions.c = builder.constant({type: operandType, dimensions: options.c.shape}, new TestTypedArray(options.c.data));
}
}
if (options.alpha !== undefined) {
// scalar
gemmOptions.alpha = new TestTypedArray([options.alpha])[0];
}
if (options.beta !== undefined) {
// scalar
gemmOptions.beta = new TestTypedArray([options.beta])[0];
}
if (options.aTranspose !== undefined) {
gemmOptions.aTranspose = options.aTranspose;
}
if (options.bTranspose !== undefined) {
gemmOptions.bTranspose = options.bTranspose;
}
}
return builder.gemm(inputOperandA, inputOperandB, gemmOptions);
};

testWebNNOperation('gemm', '/webnn/resources/test_data/gemm.json', computeGemm);
17 changes: 17 additions & 0 deletions webnn/matmul.https.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// META: title=test WebNN API matmul operation
// META: global=window,dedicatedworker
// META: script=./resources/utils.js
// META: timeout=long

'use strict';

// https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-matmul

const computeMatmul = (builder, resources) => {
// MLOperand matmul(MLOperand a, MLOperand b);
// use 'a' and 'b' for input operands name
const [inputOperandA, inputOperandB] = createInputOperands(builder, resources, ['a', 'b']);
return builder.matmul(inputOperandA, inputOperandB);
};

testWebNNOperation('matmul', '/webnn/resources/test_data/matmul.json', computeMatmul);
17 changes: 17 additions & 0 deletions webnn/relu.https.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// META: title=test WebNN API relu operation
// META: global=window,dedicatedworker
// META: script=./resources/utils.js
// META: timeout=long

'use strict';

// https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-relu

const computeRelu = (builder, resources) => {
// MLOperand relu(MLOperand x);
// use 'x' for input operand name
const [inputOperand] = createInputOperands(builder, resources, ['x']);
return builder.relu(inputOperand);
};

testWebNNOperation('relu', '/webnn/resources/test_data/relu.json', computeRelu);
18 changes: 18 additions & 0 deletions webnn/reshape.https.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// META: title=test WebNN API reshape operation
// META: global=window,dedicatedworker
// META: script=./resources/utils.js
// META: timeout=long

'use strict';

// https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-reshape

const computeReshape = (builder, resources) => {
// MLOperand reshape(MLOperand input, sequence<long> newShape);
// use 'input' for input operand name
const [inputOperand] = createInputOperands(builder, resources, ['input']);
return builder.reshape(inputOperand, resources.newShape);
};

testWebNNOperation('reshape', '/webnn/resources/test_data/reshape.json', computeReshape);

Loading