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

[js/webgpu] Float16Array polyfill for uniform #19307

Closed
wants to merge 42 commits into from

Conversation

axinging
Copy link
Contributor

@axinging axinging commented Jan 29, 2024

To use this feature, first create a f16 model from f32 model:

import onnxruntime as ort
import onnx
from onnx import helper as helper
from onnx import TensorProto as tp
import numpy as np
import onnx
from onnxconverter_common import float16

model = onnx.load("pad_constant_f32_opset8.onnx")
model_fp16 = float16.convert_float_to_float16(model)
onnx.save(model_fp16, "pad_constant_f16_opset8.onnx")

Then test it like this:

  <script src="./web/dist/ort.all.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/@petamoriken/float16/browser/float16.min.js"></script>
  <script>
    const { Float16Array } = float16;
    async function main() {
      try {
        const session = await ort.InferenceSession.create('./pad_constant_f16_opset8.onnx', { executionProviders: ['webgpu'] });
        let dataA = Float16Array.from([1.2, 2.5, 3.5, 4, 5, 6.1, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);

        const tensorA = new ort.Tensor('float16', dataA, [1, 3, 4, 5]);
        // prepare feeds. use model input names as keys.
        const feeds = { x: tensorA };
        const results = await session.run(feeds);
        // read from results
        const dataC = results.y.cpuData;
        console.log(`data of result tensor 'c': ${dataC}`);
      } catch (e) {
        console.error(`failed to inference ONNX model: ${e}.`);
      }
    }

    main();
  </script>

@axinging axinging changed the title Float16 polyfill v2 [js] Float16Arrry polyfill Jan 30, 2024
declare global {
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any
const Float16Array: any;
const isFloat16Array: any;
Copy link
Contributor

Choose a reason for hiding this comment

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

isFloat16Array is not going to be polyfilled in the global scope. we can still use a instanceof Float16Array to perform the check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

throw new TypeError(
'Creating a float16 tensor from number array is not supported. Please use Uint16Array as data.');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data = (typedArrayConstructor as any).from(arg1);
Copy link
Contributor

@fs-eire fs-eire Jan 30, 2024

Choose a reason for hiding this comment

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

as explained in the old error message, you cannot do typedArrayConstructor.from because it does not work with Uint16Array. you need to check if typedArrayConstructor is Float16Array. You can just use the code from that of my PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done, thanks!

@@ -168,6 +168,8 @@ export class Tensor implements TensorInterface {
}
} else if (arg1 instanceof typedArrayConstructor) {
data = arg1;
} else if (isFloat16Array !== undefined && isFloat16Array(arg1)) {
data = arg1 as InstanceType<typeof Float16Array>;
Copy link
Contributor

Choose a reason for hiding this comment

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

does the code actually call into this if branch? I assume that map NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP should already set with key 'float16', so it should be handled in condition (arg1 instanceof typedArrayConstructor)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, this is not necessary now. Thanks!

Comment on lines 244 to 245
scalesValidation(scales as number[], mode, isResize);
return scales as number[];
Copy link
Contributor

Choose a reason for hiding this comment

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

we can keep onnxjs code unchanged as they are going to deprecated. we don't plan to support new features to webgl.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Remove this may complains: $ npm run build

[email protected] prebuild
tsc -p . --noEmit && tsc -p lib/wasm/proxy-worker --noEmit

lib/onnxjs/backends/webgl/ops/resize-packed.ts:244:20 - error TS2345: Argument of type 'unknown[]' is not assignable to parameter of type 'number[]'.
Type 'unknown' is not assignable to type 'number'.

244 scalesValidation(scales, mode, isResize);
~~~~~~

lib/onnxjs/backends/webgl/ops/resize-packed.ts:245:3 - error TS2322: Type 'unknown[]' is not assignable to type 'number[]'.

245 return scales;
~~~~~~

Found 2 errors in the same file, starting at: lib/onnxjs/backends/webgl/ops/resize-packed.ts:244

Copy link
Contributor

Choose a reason for hiding this comment

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

let me try to make some modifications to unit test so that it no longer depends on onnxjs/tensor. Then you don't need to modify any file under onnxjs folder .

Copy link
Contributor

Choose a reason for hiding this comment

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

#19358 should work with it

"description": "ONNXRuntime JavaScript API library"
"description": "ONNXRuntime JavaScript API library",
"dependencies": {
"@petamoriken/float16": "^3.8.4"
Copy link
Contributor

Choose a reason for hiding this comment

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

please add as devDependencies

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -11,6 +11,7 @@
"version": "1.18.0",
"jsdelivr": "dist/ort.min.js",
"dependencies": {
"@petamoriken/float16": "^3.8.4",
Copy link
Contributor

Choose a reason for hiding this comment

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

please add as devDependencies

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -1,14 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import {Float16Array} from '@petamoriken/float16';
Copy link
Contributor

Choose a reason for hiding this comment

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

no need to add this as we don't plan to add f16 support for webgl

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@axinging axinging changed the title [js] Float16Arrry polyfill [js] Float16Array polyfill Jan 30, 2024
@@ -34,7 +35,7 @@ export const BIGINT_TYPES = [
/**
* float16 type, data represented by Uint16Array
*/
export const FLOAT16_TYPE = ['float16', Uint16Array, false] as const;
export const FLOAT16_TYPE = ['float16', Float16Array, false] as const;
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest not to update this part. Both paths (with and without polyfill) need to be tested. to test f16 polyfill, may need to add a separated target.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor Author

@axinging axinging left a comment

Choose a reason for hiding this comment

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

declare global {
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any
const Float16Array: any;
const isFloat16Array: any;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

"description": "ONNXRuntime JavaScript API library"
"description": "ONNXRuntime JavaScript API library",
"dependencies": {
"@petamoriken/float16": "^3.8.4"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -11,6 +11,7 @@
"version": "1.18.0",
"jsdelivr": "dist/ort.min.js",
"dependencies": {
"@petamoriken/float16": "^3.8.4",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

throw new TypeError(
'Creating a float16 tensor from number array is not supported. Please use Uint16Array as data.');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data = (typedArrayConstructor as any).from(arg1);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done, thanks!

@@ -168,6 +168,8 @@ export class Tensor implements TensorInterface {
}
} else if (arg1 instanceof typedArrayConstructor) {
data = arg1;
} else if (isFloat16Array !== undefined && isFloat16Array(arg1)) {
data = arg1 as InstanceType<typeof Float16Array>;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, this is not necessary now. Thanks!

Comment on lines 244 to 245
scalesValidation(scales as number[], mode, isResize);
return scales as number[];
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Remove this may complains: $ npm run build

[email protected] prebuild
tsc -p . --noEmit && tsc -p lib/wasm/proxy-worker --noEmit

lib/onnxjs/backends/webgl/ops/resize-packed.ts:244:20 - error TS2345: Argument of type 'unknown[]' is not assignable to parameter of type 'number[]'.
Type 'unknown' is not assignable to type 'number'.

244 scalesValidation(scales, mode, isResize);
~~~~~~

lib/onnxjs/backends/webgl/ops/resize-packed.ts:245:3 - error TS2322: Type 'unknown[]' is not assignable to type 'number[]'.

245 return scales;
~~~~~~

Found 2 errors in the same file, starting at: lib/onnxjs/backends/webgl/ops/resize-packed.ts:244

@@ -34,7 +35,7 @@ export const BIGINT_TYPES = [
/**
* float16 type, data represented by Uint16Array
*/
export const FLOAT16_TYPE = ['float16', Uint16Array, false] as const;
export const FLOAT16_TYPE = ['float16', Float16Array, false] as const;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@axinging axinging marked this pull request as ready for review January 30, 2024 03:34
{
"name": "constant 2D",
"operator": "Pad",
"opset": { "domain": "", "version": 10 },
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you also add a test for version > 10, in which the value is as an input not attribute and have the type float16? I suppose this can test the float16 uniform?

Do you need to update the code here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@axinging axinging marked this pull request as draft January 30, 2024 06:11
@axinging axinging marked this pull request as ready for review January 31, 2024 07:42
@axinging axinging changed the title [js] Float16Array polyfill [js/web] Float16Array polyfill Feb 1, 2024
@axinging axinging marked this pull request as draft February 22, 2024 00:55
test/test-main.ts:18:12 - error TS2339: Property 'Float16Array' does not exist on type 'typeof globalThis'.

18 globalThis.Float16Array = Float16Array;
@axinging axinging changed the title [js/web] Float16Array polyfill [js/webgpu] Float16Array polyfill Feb 22, 2024
@axinging axinging changed the title [js/webgpu] Float16Array polyfill [js/webgpu] Float16Array polyfill for uniform Feb 23, 2024
@axinging axinging marked this pull request as ready for review February 23, 2024 02:38
@axinging axinging marked this pull request as draft February 23, 2024 06:38
@axinging
Copy link
Contributor Author

This is replaced by:
#21691

@axinging axinging closed this Aug 27, 2024
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.

3 participants