-
Notifications
You must be signed in to change notification settings - Fork 3
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
base: master
Are you sure you want to change the base?
Conversation
createContext() / createContextSync() build() / buildSync() compute() / computeSync()
inputDataCategory -> inputDataSource expectedDataCategory -> expectedDataSource
return builder.clamp(inputOperand, resources.options); | ||
}; | ||
|
||
testWebNNOperation('clamp', '/webnn/resources/test_data/clamp.json', computeClamp); |
There was a problem hiding this comment.
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);
There was a problem hiding this comment.
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": [ |
There was a problem hiding this comment.
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": { |
There was a problem hiding this comment.
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
Line 13 in 3edeb4c
const [inputOperandA, inputOperandB] = createInputOperands(builder, resources, ['a', 'b']); |
"tests": [ // relu the same input test data of 1D ~ 5D shapes | ||
{ | ||
"name": "relu 1D input", | ||
"inputs": { |
There was a problem hiding this comment.
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
Line 13 in 3edeb4c
const [inputOperand] = createInputOperands(builder, resources, ['x']); |
const TestTypedArray = TypedArrayDict[operandType]; | ||
const options = resources.options; | ||
const gemmOptions = {}; | ||
if (options !== undefined) { |
There was a problem hiding this comment.
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": [ |
There was a problem hiding this comment.
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.
No description provided.