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

[webgpu] Update INT_DIV #7792

Merged
merged 2 commits into from
Jul 17, 2023
Merged

[webgpu] Update INT_DIV #7792

merged 2 commits into from
Jul 17, 2023

Conversation

hujiajie
Copy link
Contributor

To see the logs from the Cloud Build CI, please join either our discussion or announcement mailing list.

Copy link
Contributor

@qjia7 qjia7 left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@qjia7 qjia7 requested review from gyagp and xhcao June 30, 2023 06:08
let remainder = round(numerator % denominator);
let quotient = round((numerator - remainder) / denominator);
let resultTemp =
select(quotient, quotient - 1, sign(remainder) == -sign(denominator));
Copy link

Choose a reason for hiding this comment

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

Several questions and comments:

  1. round() in WGSL has a special definition: "Result is the integer k nearest to e, as a floating point value. When e lies halfway between integers k and k + 1, the result is k when k is even, and k + 1 when k is odd." Will this introduce a diff between CPU and WebGPU solution?
  2. For "let remainder = round(numerator % denominator);" Is round() necessary?
  3. What's the result of "9 / (-2)" in this code?
  4. numerator -> dividend, denominator -> divisor?
  5. Please ensure we have enough unit test cases for them, especially when dividend and/or divisor are halfway between integers, the results from "(numerator - remainder) / denominator" are halfway between integers, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Several questions and comments:

  1. round() in WGSL has a special definition: "Result is the integer k nearest to e, as a floating point value. When e lies halfway between integers k and k + 1, the result is k when k is even, and k + 1 when k is odd." Will this introduce a diff between CPU and WebGPU solution?

This is not clearly mentioned in the TensorFlow.js API doc. Even if the CPU rounding mode differs from the GPU backend, I cannot tell which one is more correct, or if either is fine.

  1. For "let remainder = round(numerator % denominator);" Is round() necessary?

No, but I feel that's more aligned with neighboring lines.

  1. What's the result of "9 / (-2)" in this code?

-5

  1. numerator -> dividend, denominator -> divisor?

The API doc prefers numerator/denominator.

  1. Please ensure we have enough unit test cases for them, especially when dividend and/or divisor are halfway between integers, the results from "(numerator - remainder) / denominator" are halfway between integers, etc.

Copy link

Choose a reason for hiding this comment

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

Different languages may have different results.
[python]
(-9) % 2 -> 1
9 % (-2) -> -1

[JavaScript]
(-9) % 2 -> -1
9 % (-2) -> 1

So your result will be at least different from the JS's result.
With round(), we introduce another level of difference between CPU and GPU, at least for the quotient calculation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please note INT_DIV is exclusively used by floorDiv(), and the doc states the result should be floored. This matches with the current CPU behavior (Math.floor(a / b)).

Copy link
Contributor

Choose a reason for hiding this comment

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

JiaJie, if INT_DIV is only used for floorDiv, will it be better to rename INT_DIV to FLOOR_DIV?

@jiangzhaoming
Copy link

jiangzhaoming commented Jul 3, 2023

I have concern that the whole implementation of INT_DIV and floorDiv may conflict their expected semantic. The implementation, before and after this PR, is not coherent with floor(x/y), which is the definition of floorDiv(x, y). It only works correctly for integer input, and actually only tested on int32.
For example, input (5.9, 2) will result in 6.0 / 2.0 = 3.0 instead of floor(5.9 / 2.0) = floor(2.95) = 2.0, and input (3.7, 1.9) will result in 4.0 / 2.0 = 2.0 instead of floor(3.7 / 1.9) = floor(1.947368...) = 1.0. Input (5.4, 2.7) will result in 1.0 instead of 2.0.
I think the round of two inputs in original implementation are intend for handling integer inputs passing to WebGL as float, and we should revisit them.

Copy link
Contributor

@qjia7 qjia7 left a comment

Choose a reason for hiding this comment

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

Good work, Jiajie. Please also add some test cases for float32 type in tfjs-core.

Copy link

@gyagp gyagp left a comment

Choose a reason for hiding this comment

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

I defer to Zhaoming's review on this.

@hujiajie hujiajie closed this Jul 7, 2023
@qjia7
Copy link
Contributor

qjia7 commented Jul 13, 2023

@jzm-intel Do you have any concern with the latest change? The test can be found here #7809.

Copy link

@jiangzhaoming jiangzhaoming left a comment

Choose a reason for hiding this comment

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

LGTM, thanks

export const floorDiv = binaryKernelFunc({
opType: BinaryOpType.FLOOR_DIV,
cpuKernelImpl: floorDivImplCPU,
dtype: 'int32'

Choose a reason for hiding this comment

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

Why does it state as 'int32'? This is the last thing that confuse me....

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the result dtype.

Choose a reason for hiding this comment

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

Thanks, still LGTM.

@gyagp gyagp merged commit d45c6af into tensorflow:master Jul 17, 2023
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.

4 participants