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

Fix Incorrect derivative when loops contains continue #833

Merged
merged 11 commits into from
Oct 30, 2024

Conversation

kchristin22
Copy link
Collaborator

@kchristin22 kchristin22 commented Mar 20, 2024

For more details please see #710 (comment). This PR concerns only the fix of #710, so the only change needed is the one regarding the position of the step of the forward loop's variable in the reverse pass. Tests need to be updated accordingly if the change is approved.

Closes #710, closes #851.

Copy link
Contributor

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Collaborator

@parth-07 parth-07 left a comment

Choose a reason for hiding this comment

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

Thank you for the pull-request. The solution seems good. Can you please add tests and update the pull-request description?

Also, can you please open an issue regarding fixing incorrect derivatives when loops contains break? You can use this test case:

#include "clad/Differentiator/Differentiator.h"
#include <iostream>

#define show(x) std::cout << #x << ": " << x << "\n";

double fn(double u, double v) {
    double res = 0;
    for (int i = 1; i < 3; i++) {
        res += i * u;
        if (i == 1)
            break;
    }
    return res;
}

int main() {
    auto d_fn = clad::gradient(fn);
    double u = 3, v = 5;
    double du, dv;
    du = dv = 0;
    d_fn.execute(u, v, &du, &dv);
    show(du);
    show(dv);
}

activeBreakContHandler->EndCFSwitchStmtScope();
activeBreakContHandler->UpdateForwAndRevBlocks(bodyDiff);
PopBreakContStmtHandler();

// Increment statement in the for-loop is only executed if the iteration
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please update this comment.

@kchristin22
Copy link
Collaborator Author

I will update the tests, the description and the comment.

Also, can you please open an issue regarding fixing incorrect derivatives when loops contains break? You can use this test case:

Sure thing!

@kchristin22
Copy link
Collaborator Author

kchristin22 commented Mar 25, 2024

Upon checking out the above example, the error occurs after the change of this PR right? I noticed that the decrement of i-- should be after the switch case when there's a break stmt as otherwise we "miss" a value of i. I will open a new PR for the new issue after this PR is merged.

@parth-07
Copy link
Collaborator

the error occurs after the change of this PR right?

Yes, however, the break statement had incorrect behavior without this PR change as well. It's just that the particular example that I added happen to work for Clad on master.

I noticed that the decrement of i-- should be after the switch case when there's a break stmt as otherwise we "miss" a value of i.

In the case of a break statement, the last increment does not happen. So we need to skip the corresponding decrement as well when the break statement is hit.

@kchristin22
Copy link
Collaborator Author

I have not forgotten this. I will update it in the upcoming week. Sorry for the delay.

Copy link
Contributor

github-actions bot commented Apr 4, 2024

clang-tidy review says "All clean, LGTM! 👍"

Copy link

codecov bot commented Apr 4, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 94.43%. Comparing base (b8de117) to head (1bae2cd).
Report is 1 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #833      +/-   ##
==========================================
+ Coverage   94.42%   94.43%   +0.01%     
==========================================
  Files          50       50              
  Lines        8729     8751      +22     
==========================================
+ Hits         8242     8264      +22     
  Misses        487      487              
Files with missing lines Coverage Δ
include/clad/Differentiator/ReverseModeVisitor.h 97.41% <100.00%> (+0.09%) ⬆️
lib/Differentiator/ReverseModeVisitor.cpp 95.66% <100.00%> (+0.02%) ⬆️
Files with missing lines Coverage Δ
include/clad/Differentiator/ReverseModeVisitor.h 97.41% <100.00%> (+0.09%) ⬆️
lib/Differentiator/ReverseModeVisitor.cpp 95.66% <100.00%> (+0.02%) ⬆️

Copy link
Contributor

github-actions bot commented Apr 4, 2024

clang-tidy review says "All clean, LGTM! 👍"

1 similar comment
Copy link
Contributor

github-actions bot commented Apr 4, 2024

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Collaborator

@parth-07 parth-07 left a comment

Choose a reason for hiding this comment

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

Can you please add a test case where Clad was giving incorrect derivative result before?

Copy link
Contributor

github-actions bot commented Apr 6, 2024

clang-tidy review says "All clean, LGTM! 👍"

@kchristin22
Copy link
Collaborator Author

kchristin22 commented Apr 6, 2024

@parth-07 I tried to add a new function in Loops.C, but even though I get the correct result when I compile locally this file and run it, somehow when I test using make check-clad, the result is expected to be 15.00 and if I change that to 15.00 it then says that the result of fn21 is expected to be 7.00 (which is correct). The fn21_grad function printed as a log due to the error also doesn't match the one that was checked and succeeded.

Update: the problem lies in TBR analysis, the increment is not included. I'm working on it.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

include/clad/Differentiator/Differentiator.h Show resolved Hide resolved
CreateCFTapeSizeExprForCurrentCase() {
return m_RMV.BuildOp(BinaryOperatorKind::BO_NE, m_ControlFlowTape->Size(),
ConstantFolder::synthesizeLiteral(
m_RMV.m_Context.IntTy, m_RMV.m_Context, 0));
Copy link
Contributor

Choose a reason for hiding this comment

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

warning: argument comment missing for literal argument 'val' [bugprone-argument-comment]

Suggested change
m_RMV.m_Context.IntTy, m_RMV.m_Context, 0));
m_RMV.m_Context.IntTy, m_RMV.m_Context, /*val=*/0));

Copy link
Owner

Choose a reason for hiding this comment

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

Maybe we should use the new ZeroInit interface here that you wrote?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since this doesn't refer to an initialization, I think ConstantFolder::synthesizeLiteral is a better fit. getZeroInit calls this function internally either way.

Copy link
Collaborator

@parth-07 parth-07 left a comment

Choose a reason for hiding this comment

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

Can you please add tests as well?

@vgvassilev
Copy link
Owner

Can we undo the formatting changes which are not related to the changes of this pr?

@kchristin22
Copy link
Collaborator Author

Can we undo the formatting changes which are not related to the changes of this pr?

Yes sorry about that, I was trying to fix it, cause my local version of git-clang-format produces different results than the CI. I think now it includes only the necessary changes more or less.

@parth-07
Copy link
Collaborator

@kchristin22 Can you please add tests in the PR?

@@ -2081,19 +2086,19 @@ double fn26(double i, double j) {
// CHECK-NEXT: if (!_t0)
// CHECK-NEXT: break;
// CHECK-NEXT: }
// CHECK-NEXT: {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@PetroZarytskyi @ovdiiuv without using TBR, this follows the pattern of avoiding performing the increment differentiation step when this is the case of the break branch. So, this is derived like so when TBR analysis is not performed:

if (clad::size(_t3) != 0 && clad::back(_t3) != 1) {
            res = clad::pop(_t2);
            double _r_d1 = _d_res;
            _d_res = 0.;
            *_d_i += 7 * _r_d1 * j;
            *_d_j += 7 * i * _r_d1;
            _d_c += 0;
            --c;
}

It seems that when the increment's diff is a compound stmt this is instead:

{
           res = clad::pop(_t2);
           double _r_d1 = _d_res;
           _d_res = 0.;
           *_d_i += 7 * _r_d1 * j;
           *_d_j += 7 * i * _r_d1;
           _d_c += 0;
           --c;
}

Is this intentional? Should I open an issue for this?

CreateCFTapeSizeExprForCurrentCase() {
return m_RMV.BuildOp(BinaryOperatorKind::BO_NE, m_ControlFlowTape->Size(),
ConstantFolder::synthesizeLiteral(
m_RMV.m_Context.IntTy, m_RMV.m_Context, 0));
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since this doesn't refer to an initialization, I think ConstantFolder::synthesizeLiteral is a better fit. getZeroInit calls this function internally either way.

test/Gradient/Loops.C Outdated Show resolved Hide resolved
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

m_CurrentBreakFlagExpr =
BuildOp(BinaryOperatorKind::BO_LOr,
BuildOp(BinaryOperatorKind::BO_NE, revCounter,
BuildDeclRef(loopCounter.getNumRevIterations())),
Copy link
Contributor

Choose a reason for hiding this comment

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

warning: initializing non-owner 'DefaultStmt *' with a newly created 'gsl::owner<>' [cppcoreguidelines-owning-memory]

    auto* newDefaultStmt =
    ^

test/Gradient/Loops.C Outdated Show resolved Hide resolved
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

// Increment statement in the for-loop is only executed if the iteration
// did not end with a break/continue statement. Therefore, forLoopIncDiff
// should be inside the last switch case in the reverse pass.
activeBreakContHandler->EndCFSwitchStmtScope();
Copy link
Contributor

Choose a reason for hiding this comment

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

warning: use auto when initializing with a template cast to avoid duplicating the type name [modernize-use-auto]

Suggested change
activeBreakContHandler->EndCFSwitchStmtScope();
auto* forwardSS =

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

clang-tidy made some suggestions

}

/// Returns the number of reverse iterations to be executed.
clang::VarDecl* getNumRevIterations() const { return m_numRevIterations; }
Copy link
Contributor

Choose a reason for hiding this comment

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

warning: function 'getNumRevIterations' should be marked [[nodiscard]] [modernize-use-nodiscard]

Suggested change
clang::VarDecl* getNumRevIterations() const { return m_numRevIterations; }
[[nodiscard]] clang::VarDecl* getNumRevIterations() const { return m_numRevIterations; }

Copy link
Collaborator

@parth-07 parth-07 left a comment

Choose a reason for hiding this comment

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

Looks good.

@vgvassilev vgvassilev merged commit 21e4b4f into vgvassilev:master Oct 30, 2024
90 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants