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

Generate baseline data script for operator with single input #78

Merged
merged 6 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@
"eslint-plugin-jsdoc": "^30.3.1",
"eslint-plugin-prefer-arrow": "^1.2.2",
"mocha": "^9.0.3"
},
"dependencies": {
"@petamoriken/float16": "^3.8.7"
}
}
28 changes: 28 additions & 0 deletions test/tools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
How to generate test-data file for WPT tests?

Step 1: Please prepare resources JSON file which includes those tests
to test each operator of WebNN API without specified inputs and outputs
data.

Step 2: Generate test-data scripts

Step 3: Execute command for generating test-data files for WPT tests.
```shell
node gen-operator-with-single-input.js resources\<operator>.json
```

Take an example for softsign operator tests:

```shell
node gen-operator-with-single-input.js resources\softsign.json
```

Then you can find two generated folders named 'test-data' and
'test-data-wpt'. They're raw test data as being
./test-data/softsign-data.json,
and raw WPT test-data file as being ./test-data-wpt/softsign.json.


You can manually modify some test data in
./test-data/softsign-data.json,
then execute Step 3, to update ./test-data-wpt/softsign.json.
79 changes: 79 additions & 0 deletions test/tools/gen-operator-with-single-input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use strict';

/* eslint guard-for-in: 0 */

import path from 'path';
import {softsign} from '../../src/softsign.js';
import {gelu} from '../../src/gelu.js';
import {Tensor} from '../../src/lib/tensor.js';
import {utils} from './utils.js';

(() => {
function computeBySingleInput(operatorName, input, options = {}) {
const operatorMappingDict = {
'gelu': gelu,
'softsign': softsign,
};
const inputTensor = new Tensor(input.shape, input.data);
const outputTensor = operatorMappingDict[operatorName](inputTensor, options);
return outputTensor.data;
}

const operatorString = path.basename(process.argv[2], '.json');
const savedDataFile = path.join(
path.dirname(process.argv[1]), 'test-data',
`${operatorString}-data.json`);
const jsonDict = utils.readJsonFile(process.argv[2]);
const inputsDataInfo = jsonDict.inputsData;
const toSaveDataDict = utils.prepareInputsData(
inputsDataInfo, savedDataFile, jsonDict.inputsDataRange);
toSaveDataDict['expectedData'] = {};
const tests = jsonDict.tests;
const wptTests = JSON.parse(JSON.stringify(tests));
for (const test of tests) {
console.log(`Test case name: ${test.name}`);
const precisionDataInput = utils.getPrecisionDataFromDataDict(
toSaveDataDict['inputsData'], test.inputs.input.data,
test.inputs.input.dataType);
const input = {shape: test.inputs.input.shape, data: precisionDataInput};
const result = computeBySingleInput(operatorString, input, test.options);
toSaveDataDict['expectedData'][test.expected.data] =
utils.getPrecisionData(result, test.expected.dataType);
}

utils.writeJsonFile(toSaveDataDict, savedDataFile);
console.log(`[ Done ] Saved test data into ${savedDataFile}.`);

const wptConformanceTestsDict = {tests: []};
for (const test of wptTests) {
// update inputs data
for (const inputName in test.inputs) {
test.inputs[inputName].data =
typeof test.inputs[inputName].data === 'number' ||
(typeof test.inputs[inputName].data === 'object' &&
typeof test.inputs[inputName].data[0] === 'number') ?
test.inputs[inputName].data :
utils.getPrecisionDataFromDataDict(
toSaveDataDict['inputsData'], test.inputs[inputName].data,
test.inputs[inputName].dataType);
}
// update weights (scale, bias, and etc.) data of options
if (test.options) {
for (const optionName in test.options) {
if (test.options[optionName].data) {
test.options[optionName].data =
toSaveDataDict['inputsData'][test.options[optionName].data];
}
}
}
// update expected data
test.expected.data = toSaveDataDict['expectedData'][test.expected.data];
wptConformanceTestsDict.tests.push(test);
}

const savedWPTDataFile = path.join(
path.dirname(process.argv[1]), 'test-data-wpt', `${operatorString}.json`);
utils.writeJsonFile(wptConformanceTestsDict, savedWPTDataFile);

console.log(`[ Done ] Generate test data file ${savedWPTDataFile} for WPT tests.`);
})();
218 changes: 218 additions & 0 deletions test/tools/resources/gelu.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
{
"tests": [
{
"name": "gelu float32 0D scalar",
"inputs": {
"input": {
"shape": [],
"data": "float32DataScalarInput",
"dataType": "float32"
}
},
"expected": {
"name": "output",
"shape": [],
"data": "float32DataScalarOutput",
"dataType": "float32"
}
},
{
"name": "gelu float16 0D scalar",
"inputs": {
"input": {
"shape": [],
"data": "float16DataScalarInput",
"dataType": "float16"
}
},
"expected": {
"name": "output",
"shape": [],
"data": "float16DataScalarOutput",
"dataType": "float16"
}
},
{
"name": "gelu float32 1D tensor",
"inputs": {
"input": {
"shape": [24],
"data": "float32DataInput",
"dataType": "float32"
}
},
"expected": {
"name": "output",
"shape": [24],
"data": "float32DataOutput",
"dataType": "float32"
}
},
{
"name": "gelu float16 1D tensor",
"inputs": {
"input": {
"shape": [24],
"data": "float16DataInput",
"dataType": "float16"
}
},
"expected": {
"name": "output",
"shape": [24],
"data": "float16DataOutput",
"dataType": "float16"
}
},
{
"name": "gelu float32 2D tensor",
"inputs": {
"input": {
"shape": [4, 6],
"data": "float32DataInput",
"dataType": "float32"
}
},
"expected": {
"name": "output",
"shape": [4, 6],
"data": "float32DataOutput",
"dataType": "float32"
}
},
{
"name": "gelu float16 2D tensor",
"inputs": {
"input": {
"shape": [4, 6],
"data": "float16DataInput",
"dataType": "float16"
}
},
"expected": {
"name": "output",
"shape": [4, 6],
"data": "float16DataOutput",
"dataType": "float16"
}
},
{
"name": "gelu float32 3D tensor",
"inputs": {
"input": {
"shape": [2, 3, 4],
"data": "float32DataInput",
"dataType": "float32"
}
},
"expected": {
"name": "output",
"shape": [2, 3, 4],
"data": "float32DataOutput",
"dataType": "float32"
}
},
{
"name": "gelu float16 3D tensor",
"inputs": {
"input": {
"shape": [2, 3, 4],
"data": "float16DataInput",
"dataType": "float16"
}
},
"expected": {
"name": "output",
"shape": [2, 3, 4],
"data": "float16DataOutput",
"dataType": "float16"
}
},
{
"name": "gelu float32 4D tensor",
"inputs": {
"input": {
"shape": [2, 2, 2, 3],
"data": "float32DataInput",
"dataType": "float32"
}
},
"expected": {
"name": "output",
"shape": [2, 2, 2, 3],
"data": "float32DataOutput",
"dataType": "float32"
}
},
{
"name": "gelu float16 4D tensor",
"inputs": {
"input": {
"shape": [2, 2, 2, 3],
"data": "float16DataInput",
"dataType": "float16"
}
},
"expected": {
"name": "output",
"shape": [2, 2, 2, 3],
"data": "float16DataOutput",
"dataType": "float16"
}
},
{
"name": "gelu float32 5D tensor",
"inputs": {
"input": {
"shape": [2, 1, 4, 1, 3],
"data": "float32DataInput",
"dataType": "float32"
}
},
"expected": {
"name": "output",
"shape": [2, 1, 4, 1, 3],
"data": "float32DataOutput",
"dataType": "float32"
}
},
{
"name": "gelu float16 5D tensor",
"inputs": {
"input": {
"shape": [2, 1, 4, 1, 3],
"data": "float16DataInput",
"dataType": "float16"
}
},
"expected": {
"name": "output",
"shape": [2, 1, 4, 1, 3],
"data": "float16DataOutput",
"dataType": "float16"
}
}
],
"inputsData": {
"float32DataScalarInput": {
"shape": [1],
"dataType": "float32"
},
"float32DataInput": {
"shape": [24],
"dataType": "float32"
},
"float16DataScalarInput": {
"shape": [1],
"dataType": "float16"
},
"float16DataInput": {
"shape": [24],
"dataType": "float16"
}
},
"inputsDataRange": {
"max": 1,
"min": -1
}
}
Loading
Loading