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
Open

Conversation

BruceDai
Copy link
Owner

No description provided.

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.

// concat 1D tensors
{
"name": "concat two 1D of same shape along axis 0",
"inputs": [
Copy link
Owner Author

Choose a reason for hiding this comment

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

Here inputs is an array for first parameter of concat(), to create input operands easily, I use operand name likes input1, input2, input3, ... .

{
"name": "gemm with default options",
"inputs": {
"a": {
Copy link
Owner Author

Choose a reason for hiding this comment

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

Here inputs is a dictionary, it has a and b to align with two parameters of gemm(MLOperand a, MLOperand b, optional MLGemmOptions options = {}); };, the key 'a' and 'b' are used for input operands name, which would used to create input operands on

const [inputOperandA, inputOperandB] = createInputOperands(builder, resources, ['a', 'b']);

"tests": [ // relu the same input test data of 1D ~ 5D shapes
{
"name": "relu 1D input",
"inputs": {
Copy link
Owner Author

Choose a reason for hiding this comment

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

Here inputs is also dictionary, which has "x" input to align with relu(MLOperand x);, the key 'x' is as input operand name by code

const [inputOperand] = createInputOperands(builder, resources, ['x']);

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);

"inputs": {
"x": { // use 'x' for input operand name
"shape": [24],
"data": [
Copy link
Owner Author

Choose a reason for hiding this comment

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

Use explicit test data for input and expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant