-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[webnn] Add tests for concat operation. #36782
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
[webnn] Add tests for concat operation. #36782
Conversation
| } | ||
| }, | ||
| "inputsData": { | ||
| "float64Data": [ |
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.
These inputsData and below expectedData were automatically generated by this scripts of WebNN-Baseline project.
822cb63 to
16985d3
Compare
7617c56 to
a34c3cd
Compare
webnn/concat.https.any.js
Outdated
| graph = await builder.build({outputOperand}); | ||
| await context.compute(graph, namedInputs, outputs); | ||
| } | ||
| assert_array_approx_equals_ulp(outputs.outputOperand, expectedShapeValue.data, PrecisionMetrics.concat.ULP[operandType], operandType); |
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.
[minor] Hmm, why does this function name use snake case whereas nearly every other function and variable uses camelCase? (e.g. sizeOfShape, computeSync, loadTestData)?
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.
The assertion function assert_array_approx_equals_ulp() was intended to add into testharness.js previously, so its' name followed like function assert_array_equals() of testharness.js.
Since assert_array_approx_equals_ulp() is especial for WebNN API tests, I'm OK to use camelCase style.
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 see. So there was some external convention.
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.
Yes.
I go through some wpt tests of others features, there are common problems for variable/function name with snake case or camelCase ... :(
So what's your suggestion for this assertion function? Thanks.
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.
Oh, I generally lean toward internal consistency with whatever code is immediately around it, but there's also the consistency argument of matching other "assert_" functions. I'm fine with whichever you decide - you answered my question either way. ✅
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 leave this assert to be consistent with other "assert_" functions in testharness.js, thanks.
webnn/resources/utils.js
Outdated
| distance = actualBitwise - expectedBitwise; | ||
| distance = distance >= 0 ? distance : -distance; | ||
| assert_true(distance <= nulp, | ||
| `actual ${actual[i]} should be close enough to expected ${expected[i]} by the acceptable ${nulp} ULP distance, while they have ${distance} ULP distance`); |
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.
Propose "while" -> "but".
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.
Updated, thanks.
|
|
||
| // Refer to precision metrics on https://github.com/webmachinelearning/webnn/issues/265#issuecomment-1256242643 | ||
| const PrecisionMetrics = { | ||
| concat: {ULP: {float32: 0, float16: 0}}, |
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.
Nice, thanks for the order update.
webnn/concat.https.any.js
Outdated
| } | ||
| const expectedShapeValue = {shape: test.expected.shape, data: expectedData[expectedDataCategory]}; | ||
| await testConcat(operandType, isSync, inputShapeValues, test.axis, expectedShapeValue); | ||
| }, `${test.name} / ${operandType} / ${deviceType} / ${executionType}`); |
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.
[ignorable] I notice you usually put a new line after most }'s, and so at first glance, it looked like a typo here, as I couldn't tell if the brace was in the wrong place for the for loop, not realizing it was a second parameter to the promise call. So new line after the },? (note I'm not familiar with Javascript common style conventions, but some I find easier to visually parse than others 🤷)
webnn/concat.https.any.js
Outdated
| for (const shape of inputShapes) { | ||
| const size = sizeOfShape(shape); | ||
| inputShapeValues.push({shape, data: inputsData[inputDataCategory].slice(pos, pos + size)}); | ||
| pos += size; |
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.
How about position or offset? (I just like full words :))
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.
Updated, thanks.
webnn/resources/utils.js
Outdated
| } | ||
|
|
||
| const json = loadJSON(file); | ||
| return JSON.parse(json.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) => g ? "" : m)); |
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.
Nice, this way we can have comments in the JSON.
Honry
left a comment
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.
Generally LGTM, thanks @BruceDai !
BruceDai
left a comment
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.
webnn/concat.https.any.js
Outdated
| graph = await builder.build({outputOperand}); | ||
| await context.compute(graph, namedInputs, outputs); | ||
| } | ||
| assert_array_approx_equals_ulp(outputs.outputOperand, expectedShapeValue.data, PrecisionMetrics.concat.ULP[operandType], operandType); |
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 leave this assert to be consistent with other "assert_" functions in testharness.js, thanks.
webnn/resources/utils.js
Outdated
| distance = actualBitwise - expectedBitwise; | ||
| distance = distance >= 0 ? distance : -distance; | ||
| assert_true(distance <= nulp, | ||
| `actual ${actual[i]} should be close enough to expected ${expected[i]} by the acceptable ${nulp} ULP distance, while they have ${distance} ULP distance`); |
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.
Updated, thanks.
webnn/concat.https.any.js
Outdated
| for (const shape of inputShapes) { | ||
| const size = sizeOfShape(shape); | ||
| inputShapeValues.push({shape, data: inputsData[inputDataCategory].slice(pos, pos + size)}); | ||
| pos += size; |
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.
Updated, thanks.
|
Hi @huningxin, according to your suggestion on webmachinelearning/webnn-polyfill#172, I updated this PR by invoking sync functions and async functions clearly not using |
7eefda2 to
fe02442
Compare
webnn/concat.https.any.js
Outdated
| return [{outputOperand}, inputs, outputs]; | ||
| }; | ||
|
|
||
| testWebNNOperation('concat', concatTests(), buildGraph); No newline at end of file |
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.
Hi @fdwr, @Honry and @huningxin,
I refined code to reuse for later adding other operations tests. Now each test file named <operation-name>.https.any.js will have <operation-name>Tests(), buildGraph() two functions, and run test by invoking testWebNNOperation() function, please take another look, thanks.
webnn/resources/utils.js
Outdated
| } | ||
| tolerance++; | ||
| } | ||
| break; |
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.
@fdwr I created this getPrecisonTolerance() function, and add detail implementation to get a ULP tolerance for these operations which need compute by IEPOE, please take another look, thanks.
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.
Would it be simpler to just include the function name in the table, right beside all the other values, rather than needing to fill in a switch statement (because then there are two separate places to look for values and update, a table and a code switch)? e.g.
function getGemmPrecisionTolerance(shapeA, options) {
const shapeA = resources.inputA.shape;
options = resources.options;
...
}
...
const PrecisionMetrics = {
batchNormalization: {ULP: {float32: 6, float16: 6}},
...
gemm: {ULP: {float32: getGemmPrecisionTolerance, float16: getGemmPrecisionTolerance}}
...
maxPool2d: {ULP: {float32: 0, float16: 0}},
...
};
...
function getPrecisonTolerance(opName, metricType, tensorDataType, resources) {
let tolerance;
if (metricType === 'ULP') {
tolerance = PrecisionMetrics[opName].ULP[tensorDataType];
}
else if (metricType === 'ATOL') {
tolerance = PrecisionMetrics[opName].ATOL[operandType];
}
// If the tolerance is dynamic, then evaluate the function to get the value.
if (x instanceof Function) {
tolerance = tolerance(resources);
}
return tolerance;
}
(but I'm also fine with the current code)
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.
Updated, thanks.
05e0375 to
9024b21
Compare
webnn/resources/utils.js
Outdated
| * @param {Boolean} [options.bTranspose] | ||
| * @returns {Number} A tolerance number | ||
| */ | ||
| function getGemmPrecisionTolerance(shapeA, options) { |
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.
Is there any reason that we have to put these functions inside the testWebNNOperation? This would make code not easy to read.
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.
Hi @Honry, these inner functions are only invoked by the implementation of testWebNNOperation() function, for this purpose, I define them inside, thanks.
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.
Yeah, nested functions are harder to read and discern where the beginning and end are (even if only called by that one function).
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.
Thanks for your suggestion, moved these functions outside.
|
|
||
| const TypedArrayDict = { | ||
| float32: Float32Array, | ||
| }; |
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.
(minor) We might as well fill in a few more now, given we know the other data types already (no reason to wait, right?).
int32: Int32Array,
uint32: Uint32Array,
int8: Int8Array,
uint8: Uint8Array,
(obviously float16 is harder and can come later, after deciding how to handle it)
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.
Added these code, thanks.
webnn/resources/utils.js
Outdated
| * @param {Boolean} [options.bTranspose] | ||
| * @returns {Number} A tolerance number | ||
| */ | ||
| function getGemmPrecisionTolerance(shapeA, options) { |
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.
Yeah, nested functions are harder to read and discern where the beginning and end are (even if only called by that one function).
webnn/resources/utils.js
Outdated
| } | ||
| tolerance++; | ||
| } | ||
| break; |
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.
Would it be simpler to just include the function name in the table, right beside all the other values, rather than needing to fill in a switch statement (because then there are two separate places to look for values and update, a table and a code switch)? e.g.
function getGemmPrecisionTolerance(shapeA, options) {
const shapeA = resources.inputA.shape;
options = resources.options;
...
}
...
const PrecisionMetrics = {
batchNormalization: {ULP: {float32: 6, float16: 6}},
...
gemm: {ULP: {float32: getGemmPrecisionTolerance, float16: getGemmPrecisionTolerance}}
...
maxPool2d: {ULP: {float32: 0, float16: 0}},
...
};
...
function getPrecisonTolerance(opName, metricType, tensorDataType, resources) {
let tolerance;
if (metricType === 'ULP') {
tolerance = PrecisionMetrics[opName].ULP[tensorDataType];
}
else if (metricType === 'ATOL') {
tolerance = PrecisionMetrics[opName].ATOL[operandType];
}
// If the tolerance is dynamic, then evaluate the function to get the value.
if (x instanceof Function) {
tolerance = tolerance(resources);
}
return tolerance;
}
(but I'm also fine with the current code)
webnn/resources/utils.js
Outdated
| const checkResults = (opName, operandType, namedOutputOperands, outputs, resources) => { | ||
| const metricType = PrecisionMetrics[opName] ? Object.keys(PrecisionMetrics[opName])[0] : 'ULP'; | ||
| const description = `test ${opName} ${operandType}`; | ||
| const tolerance = getPrecisonTolerance(opName, metricType, operandType, resources); |
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's possible someday that WebNN will support operators which return multiple outputs, and each output could have its own tolerance. It's not an issue yet for WebNN v1, and so I'm not worried about it, but we should keep that in mind when writing the code. The only operators I can think of right now are MAX_POOL and TOP_K, but those both expect exact results, and so both outputs have the same tolerance anyway.
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.
Yes, thanks for your insightful reminder.
BruceDai
left a comment
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.
|
|
||
| const TypedArrayDict = { | ||
| float32: Float32Array, | ||
| }; |
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.
Added these code, thanks.
webnn/resources/utils.js
Outdated
| * @param {Boolean} [options.bTranspose] | ||
| * @returns {Number} A tolerance number | ||
| */ | ||
| function getGemmPrecisionTolerance(shapeA, options) { |
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.
Thanks for your suggestion, moved these functions outside.
webnn/resources/utils.js
Outdated
| } | ||
| tolerance++; | ||
| } | ||
| break; |
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.
Updated, thanks.
webnn/resources/utils.js
Outdated
| const checkResults = (opName, operandType, namedOutputOperands, outputs, resources) => { | ||
| const metricType = PrecisionMetrics[opName] ? Object.keys(PrecisionMetrics[opName])[0] : 'ULP'; | ||
| const description = `test ${opName} ${operandType}`; | ||
| const tolerance = getPrecisonTolerance(opName, metricType, operandType, resources); |
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.
Yes, thanks for your insightful reminder.
|
@fdwr Sorry. Updated, thanks. |
fdwr
left a comment
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.
Looks nice. Thanks.
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.
Looks good with some nits, thanks!
webnn/concat.https.any.js
Outdated
|
|
||
| // https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-concat | ||
|
|
||
| const concatTests = () => { |
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.
concatTests looks common except the url of resources json file. Could it be moved to utils.js with a parameter for json file url?
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.
Hi @huningxin, thanks for your reviewing and suggestions.
Since there're different implementations (L#16 to L#29) to set targetTests for WebNN operations, for example the implementation for gemmTests likes:
for (const test of tests) {
const gemmOptions = {};
const options = test.options;
if (options !== undefined) {
if (options.c !== undefined) {
gemmOptions.c = {data: inputsData[options.c.data]};
if (options.c.shape !== undefined) {
gemmOptions.c['shape'] = options.c.shape;
}
}
if (options.alpha !== undefined) {
gemmOptions.alpha = inputsData[options.alpha.data];
}
if (options.beta !== undefined) {
gemmOptions.beta = inputsData[options.beta.data];
}
if (options.aTranspose !== undefined) {
gemmOptions.aTranspose = options.aTranspose;
}
if (options.bTranspose !== undefined) {
gemmOptions.bTranspose = options.bTranspose;
}
}
targetTests.push(
{
name: test.name,
operandType: test.type,
inputA: {shape: test.inputs.a.shape, data: inputsData[test.inputs.a.data]},
inputB: {shape: test.inputs.b.shape, data: inputsData[test.inputs.b.data]},
expected: {shape: test.expected.shape, data: {outputOperand: expectedData[test.expected.data]}},
options: gemmOptions
}
);
}and implementation for clampTests likes:
for (const test of tests) {
const expectedDataSource = test.expected.data;
const inputDataSource = test.input.data;
targetTests.push(
{
name: test.name,
operandType: test.type,
input: {shape: test.input.shape, data: inputsData[inputDataSource]},
expected: {shape: test.expected.shape, data: {outputOperand: expectedData[expectedDataSource]}},
options: test.options
}
);
}so I implemented each <operation-name>Tests function for each operation, thanks.
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.
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.
This function looks like mainly setting up the test object for targetTests. It seems to me that all information and configuration of each test object come from the JOSN file. I am wondering: could we just define all these info in the JSON file and load it into resources. I suppose we don't need different JS implementation to setup test object for different ops.
Did I miss anything?
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.
@huningxin Do you suggest add actual test data for "data"? For example
| "data": "float64Data" |
my purpose of using the index string key of input / expected data is to reuse test data, thanks.
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.
@huningxin I've updated this PR for more reuse code, please take another look. And there's a reusable tests demo on my own repo for your quickly review, thanks.
| for (let i = 0; i < inputShapeValues.length; i++) { | ||
| inputOperands.push(builder.input('input' + i, {type: operandType, dimensions: inputShapeValues[i].shape})); | ||
| inputs['input' + i] = new TestTypedArray(inputShapeValues[i].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.
The code that sets inputOperands and inputs look common for other operator tests. Could they be extract to utils.js?
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.
@huningxin Thanks for your suggestions, I will try to optimize setting inputOperands, inputs and outputs in the next PR.
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.
Building inputs from JSON looks good.
webnn/concat.https.any.js
Outdated
| inputs['input' + i] = new TestTypedArray(inputShapeValues[i].data); | ||
| } | ||
| const outputOperand = builder.concat(inputOperands, resources.axis); | ||
| const outputs = {'outputOperand': new TestTypedArray(sizeOfShape(resources.expected.shape))}; |
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.
Ditto. The code that sets outputs looks common for other operator tests.
webnn/concat.https.any.js
Outdated
| return [{outputOperand}, inputs, outputs]; | ||
| }; | ||
|
|
||
| testWebNNOperation('concat', concatTests(), buildGraph); No newline at end of file |
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.
Could this be something like
testWebNNOperation('concat', '/webnn/resources/test_data/concat.json', (inputOperands, resources) => {
return {outputOperand: builder.concat(inputOperands, resources.axis)}; });
BruceDai
left a comment
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.
@huningxin Thanks for your reviewing and suggestions, I will follow up in next PR, thanks.
webnn/concat.https.any.js
Outdated
|
|
||
| // https://webmachinelearning.github.io/webnn/#api-mlgraphbuilder-concat | ||
|
|
||
| const concatTests = () => { |
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.
Hi @huningxin, thanks for your reviewing and suggestions.
Since there're different implementations (L#16 to L#29) to set targetTests for WebNN operations, for example the implementation for gemmTests likes:
for (const test of tests) {
const gemmOptions = {};
const options = test.options;
if (options !== undefined) {
if (options.c !== undefined) {
gemmOptions.c = {data: inputsData[options.c.data]};
if (options.c.shape !== undefined) {
gemmOptions.c['shape'] = options.c.shape;
}
}
if (options.alpha !== undefined) {
gemmOptions.alpha = inputsData[options.alpha.data];
}
if (options.beta !== undefined) {
gemmOptions.beta = inputsData[options.beta.data];
}
if (options.aTranspose !== undefined) {
gemmOptions.aTranspose = options.aTranspose;
}
if (options.bTranspose !== undefined) {
gemmOptions.bTranspose = options.bTranspose;
}
}
targetTests.push(
{
name: test.name,
operandType: test.type,
inputA: {shape: test.inputs.a.shape, data: inputsData[test.inputs.a.data]},
inputB: {shape: test.inputs.b.shape, data: inputsData[test.inputs.b.data]},
expected: {shape: test.expected.shape, data: {outputOperand: expectedData[test.expected.data]}},
options: gemmOptions
}
);
}and implementation for clampTests likes:
for (const test of tests) {
const expectedDataSource = test.expected.data;
const inputDataSource = test.input.data;
targetTests.push(
{
name: test.name,
operandType: test.type,
input: {shape: test.input.shape, data: inputsData[inputDataSource]},
expected: {shape: test.expected.shape, data: {outputOperand: expectedData[expectedDataSource]}},
options: test.options
}
);
}so I implemented each <operation-name>Tests function for each operation, thanks.
webnn/concat.https.any.js
Outdated
| let position = 0; | ||
| for (const shape of inputShapes) { | ||
| const size = sizeOfShape(shape); | ||
| inputShapeValues.push({shape, data: inputsData[inputDataSource].slice(position, position + size)}); |
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.
This code is especial to concat op. To inputs of others operations, it's simply to set data. @huningxin
| for (let i = 0; i < inputShapeValues.length; i++) { | ||
| inputOperands.push(builder.input('input' + i, {type: operandType, dimensions: inputShapeValues[i].shape})); | ||
| inputs['input' + i] = new TestTypedArray(inputShapeValues[i].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.
@huningxin Thanks for your suggestions, I will try to optimize setting inputOperands, inputs and outputs in the next PR.
BruceDai
left a comment
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.
@huningxin Thanks for your reviewing and suggestions.
webnn/concat.https.any.js
Outdated
| const inputShapeValues = resources.inputShapeValues; | ||
| const operandType = resources.operandType; | ||
| const TestTypedArray = TypedArrayDict[operandType]; | ||
| const computeConcat = (builder, resources) => { |
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.
Thanks. I will update it to buildConcat.
webnn/resources/utils.js
Outdated
| aTranspose: false, | ||
| bTranspose: false | ||
| } | ||
| const options = resources.options ? resources.options : defaultOptions; |
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.
Is there any method to get this 'MLGemmOptions' from browser? Thanks.
webnn/resources/utils.js
Outdated
| * @param {String[]} nameArray | ||
| * @returns {MLOperand[]} Input operands | ||
| */ | ||
| const createInputOperands = (builder, resources, nameArray) => { |
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.
Since the inputs of concat is a sequence, it's special to other ops.
I form its inputs, like
"inputs": [
{
"name": "input1",
"shape": [12],
"data": [
-0.39444134019222243,
...
]
},
{
"name": "input2",
"shape": [12],
"data": [
0.4918989118791477,
....
]
}
],
while for inputs of clamp, I form it like
"inputs": {
"x": { // use "x" for input operand name
"shape": [12],
"data": [
-0.39444134019222243,
...
- ]
}
}
so this createInputOperands is for other ops, please see the usage on demo tests .
webnn/resources/utils.js
Outdated
| * Build a graph. | ||
| * @param {MLGraphBuilder} builder - A ML graph builder | ||
| * @param {Object} resources - Resources used for building a graph | ||
| * @param {Function} computeFunc - A compute function |
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.
Thanks, I will update it.
| 0.1211843192577362 | ||
| ] | ||
| }, | ||
| "type": "float32" |
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.
Thanks, I will update it. And is it ok to still keep "type" here to indicate that current test is for float32 precision?
36c1f89 to
c9737fc
Compare
|
@huningxin I've updated PR to address your comments, please take another look, thanks. |
c9737fc to
dabd6b0
Compare
dabd6b0 to
75094a4
Compare
|
@huningxin I updated to fix your last comments, PTAL, thanks. |
75094a4 to
e0ab7ca
Compare
e0ab7ca to
d17dab8
Compare
|
@huningxin Updated, please take another look, thanks. |
huningxin
left a comment
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.
Looks good, thanks @BruceDai !
35f9b64 to
7767126
Compare
createContext() / createContextSync()
build() / buildSync()
compute() / computeSync()
inputDataCategory -> inputDataSource expectedDataCategory -> expectedDataSource
7767126 to
de07f07
Compare
|
@dontcallmedom @Honry, I rebased with latest code, all checks have passed, PTAL, thanks. |
@fdwr This pr only has
concatoperation tests, this would make you review easily. I moved tests and test data ontoresources/test_data/concat.jsonJSON file which will make maintain test smoothly, and I also addressed some feedbacks which you commented on #34287. Please help review it, thanks a lot.@dontcallmedom @Honry @huningxin Please also take a review, thanks.