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

Support signed int divisor in onnx.Mod op #2471

Merged

Conversation

negiyas
Copy link
Collaborator

@negiyas negiyas commented Sep 1, 2023

This PR supports signed int divisor in onnx.Mod op as well as unsigned int divisor. This PR includes the conversion pass, its lit and backend tests. The following comments explain difference between return values of math.rem and onnx.Mod op.

    // "math.rem" returns "minus" for minus dividend and "plus or zero" for plus dividend.
    // We call the math.rem's return value "mathRemaider".
    // However onnx.ModOp should return "minus" for minus divisor and "plus or zero" for plus divisor.
    // we call the value that onnx.Mod op should return "onnxMod". The following table shows mathRemainder,
    // onnxMod and their diference (=onnxMod-mathRemainder) for some inputs.
    //
    // dividend                |  7  |  7 | -7 | -7 |  6 |  6 | -6 | -6 |
    // divisor                 |  3  | -3 |  3 | -3 |  3 | -3 |  3 | -3 |
    // ------------------------+-----+----+----+----+----+----+----+----+
    // mathRemainder           |  1  |  1 | -1 | -1 |  0 |  0 |  0 |  0 |
    // onnxMod                 |  1  | -2 |  2 | -1 |  0 |  0 |  0 |  0 |
    // onnxMod - mathRemainder |  0  | -3 |  3 |  0 |  0 |  0 |  0 |  0 |
    //
    // The following code shows logic to get onnxMod from mathRemainder
    //
    // int dividend, divisor;
    // int mathRemainder = diviend % divisor;
    // int adjustedRemainder = mathRemainder + divisor;
    //
    // if ((mathRemainder != 0) && ((dividend < 0) ^ (divisor < 0))) # c.f. "^" shows "exclusive or".
    //   return adjustedRemainder;
    // return mathRemainder;

@negiyas negiyas marked this pull request as draft September 1, 2023 08:56
@negiyas negiyas marked this pull request as ready for review September 6, 2023 04:42
@negiyas negiyas changed the title [WIP] Support signed int divisor in onnx.Mod op Support signed int divisor in onnx.Mod op Sep 6, 2023
@chentong319
Copy link
Collaborator

Should we use llvm srem?

@negiyas
Copy link
Collaborator Author

negiyas commented Sep 8, 2023

Should we use llvm srem?
@chentong319 Thank you for useful comments.

I investigated definitions and behavior of llvm.srem, and arith.remsi (https://mlir.llvm.org/docs/Dialects/ArithOps/#arithremsi-arithremsiop), that is converted into llvm.srem. According to the investigation, these operations support signed integers, but they cannot generate right answers when the divisor is minus. If we simply use arith.remsi for onnx.Mod, the backend tests ("test_mod_mixed_sign_int64_cpu", "test_mod_mixed_sign_int32_cpu") fail as follows.

 Mismatched elements: 2 / 6 (33.3%)
Max absolute difference: 3
Max relative difference: 1.5
 x: array([ 0,  1,  5,  0, -1,  3], dtype=int32)
 y: array([ 0, -2,  5,  0,  2,  3], dtype=int32)

Accordingly, it seems that additional logic in this PR is necessary to generate right answers for the divisor-is-minus cases.
Your comments to simplify the code are very welcome! Thank you.

chentong319
chentong319 previously approved these changes Sep 8, 2023
Copy link
Collaborator

@chentong319 chentong319 left a comment

Choose a reason for hiding this comment

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

LGTM!

// rem = rem - divisor // make rem minus
// if (divisor < 0)
// rem = rem + divisor; // make rem minus
// return rem;
Copy link
Collaborator

@chentong319 chentong319 Sep 8, 2023

Choose a reason for hiding this comment

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

The code is little tricky. To understand it, I list out the case and result according to your code (NOT the comment):

  1. dividend > 0 and divisor >0, rem unchanged
  2. dividend < 0 and divisor <0, rem = (rem+divisor) + divisor = rem + 2*divisor
  3. dividend < 0 and divisor > 0, rem = rem + divisor = rem + |divisor|
  4. dividend > 0 and divisor < 0, rem = rem+divisor = rem - |divisor|

Is the second case correct? Please fix the difference of the comment and code.
Another question: do we need to check eq to zero again at line 1156? If the original rem is not zero, it will be zero after the added calculation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@chentong319 I updated the explanation and code for the part.
Thank you for useful comments. Can you kindly check the comments and code again?

@chentong319 chentong319 dismissed their stale review September 8, 2023 17:24

I have questions in details

Copy link
Collaborator

@chentong319 chentong319 left a comment

Choose a reason for hiding this comment

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

LGTM!

@negiyas negiyas merged commit a54a48c into onnx:main Sep 13, 2023
4 checks passed
@jenkins-droid
Copy link
Collaborator

Jenkins Linux amd64 Build #12613 [push] Support signed int divis... started at 01:29

@jenkins-droid
Copy link
Collaborator

Jenkins Linux s390x Build #12625 [push] Support signed int divis... started at 02:29

@jenkins-droid
Copy link
Collaborator

Jenkins Linux ppc64le Build #11618 [push] Support signed int divis... started at 02:38

@jenkins-droid
Copy link
Collaborator

Jenkins Linux amd64 Build #12613 [push] Support signed int divis... passed after 1 hr 0 min

@jenkins-droid
Copy link
Collaborator

Jenkins Linux s390x Build #12625 [push] Support signed int divis... passed after 1 hr 24 min

@jenkins-droid
Copy link
Collaborator

Jenkins Linux ppc64le Build #11618 [push] Support signed int divis... passed after 1 hr 46 min

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants