Skip to content

update ad-level so it uses a circular flowgraph - #1079

Merged
SteveBronder merged 2 commits into
stan-dev:masterfrom
SteveBronder:fix/ad-level-circular
Dec 23, 2021
Merged

update ad-level so it uses a circular flowgraph#1079
SteveBronder merged 2 commits into
stan-dev:masterfrom
SteveBronder:fix/ad-level-circular

Conversation

@SteveBronder

Copy link
Copy Markdown
Contributor

Summary

This is a fix for the ad-level optimization. There was a bug where the monotone framework was not continuously iterating in the minimum fixed point algorithm to find the set of variables that can be made into data. This led to the algorithm stopping too early and possibly producing non-compilable C++ such as for the following model

data {
    matrix[10, 10] X_data;
}

parameters {
    matrix[10, 10] X_p;
}

transformed parameters {
    matrix[10, 10] X_tp1 = exp(X_data);
    matrix[10, 10] X_tp2 = exp(X_tp1);
    X_tp1 = X_p;
}

In the current impl the ad level optimization will think X_tp1 is an autodiff type but X_tp2 is data. Since we can't assign autodiff variables to data variables this would throw a C++ compiler error.

By connecting the end nodes to the initial nodes the minimum fixed point algorithm will continously run until no changes to the program are made. Now the above program deduces that since X_tp1 must be an autodiff type X_tp2 must be as well.

In the test model you'll see that lazy code motion actually allows X_tp2 to still be data, but that's because exp(X_data) is stored in a local variable and the code becomes the equivalent of

matrix[10, 10] X_tp2 = exp(exp(X_data));

Submission Checklist

  • Run unit tests
  • Documentation
    • If a user-facing facing change was made, the documentation PR is here:
    • OR, no user-facing changes were made

Release notes

bug fix for ad-level optimization

Copyright and Licensing

By submitting this pull request, the copyright holder is agreeing to
license the submitted work under the BSD 3-clause license (https://opensource.org/licenses/BSD-3-Clause)

@SteveBronder

Copy link
Copy Markdown
Contributor Author

@WardBrian fyi the plan is to merge this, then O1, then the NA filling fix (minus turning it on by default and just the fix) then the O1 PR

@SteveBronder
SteveBronder requested a review from rybern December 22, 2021 21:16
@SteveBronder

Copy link
Copy Markdown
Contributor Author

@rybern fyi I set you as the reviewer since a lot of this is actually your code I just modified

@rybern

rybern commented Dec 23, 2021

Copy link
Copy Markdown
Collaborator

Great, I'll have a look tomorrow

@rybern rybern left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good to me as long as those tests results are right, I didn't double check those.

One thing you could consider adding is an expect test showing that name collisions can happen with this approach. Maybe a program like

parameters {
  real x;
  real y;
}
model {
  if (x > 1) {
    int a = x;
    y ~ normal(a, 1);
  } else {
    int a = 1; // a is AD but doesn't need to be
    y ~ normal(a, 1);
  }
}

so we can see the progress when we/if we fix that

let rev_flowgraph, flowgraph_to_mir =
Monotone_framework.inverse_flowgraph_of_stmt stmt in
let fwd_flowgraph = Monotone_framework.reverse rev_flowgraph in
let (module Fwd_Flowgraph) =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Tiny nit: I'd call this Circular_Fwd_Flowgraph to distinguish it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Word!

Eigen::Matrix<local_scalar_t__, -1, -1> X_tp1;
current_statement__ = 2;
assign(X_tp1, X_d, "assigning variable X_tp1");
Eigen::Matrix<double, -1, -1> X_tp2;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Just to double check, looks like X_p is AD and X_tp1-X_tp7 are non-AD, is that right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

X_tp1 is ad but the rest are not which, with lcm, is what we expect

@SteveBronder

Copy link
Copy Markdown
Contributor Author

One thing you could consider adding is an expect test showing that name collisions can happen with this approach. Maybe a program like

Let's leave that till @VMatthijs puts in that PR

@SteveBronder

Copy link
Copy Markdown
Contributor Author

Aight think we are good! @rybern Once test passes and you approve feel free to merge

@SteveBronder
SteveBronder merged commit 35af5e5 into stan-dev:master Dec 23, 2021
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.

2 participants