Refactoring and improving constraint codegen#837
Conversation
…_ variables are declared inside loops, rather than themselves being containers.
|
Here's my understanding of how we currently handle constrains:
|
|
I think the main issue with the current setup is the separation of concerns, in two ways:
So it seems like the strategy should be either:
@seantalts @nhuurre it would be great to get your thoughts |
Can you say more about this? I think the MIR should represent code that is portable across a variety of backends. In the ones I can think of (other than Stan Math), reading and constraining are different tasks. |
|
So one relevant issue is #786 If I understand correctly @SteveBronder's new deserializer prefers constrains and reads to happen in one call: stan-dev/stan#3013 @nhuurre gave a good example where we'd like reading and constraining int the same for-loop, here: #675 (comment) They also seem coupled because reads need to know about _free__ variables Edit: Sorry, I realize now that you weren't asking how they're coupled in Stan math. Maybe ignore the first two points here, but I think they'd still be coupled by the for-loop nesting and _free__ variables in other backends. In any case, my current thinking is that the level of coupling should be determined by the backend, so Ast_to_mir shouldn't have the logic about for-loops or _free__ variables. |
|
I agree that ideally the MIR should be as platform independent as possible prior to Transform_mir, so I'm leaning toward handing this in Transform_mir |
|
What does it look like moving it to Transform_mir? A related opinion of mine is that I am fully in favor of vectorizing everything possible in the MIR now - maybe that makes all of the mentioned issues happy? I was against it originally thinking it wasn't the level we wanted for backends, but I discovered that ~all backends have vectorized ~everything :D I currently lean against adding a MIR node that is a combined Read/Constrain or Read/Unconstrain, but perhaps with vectorized versions of Read and Constrain we can get everything we want pretty easily? |
Yep! Are there issues with the free variables used in double x = context.get_free_lb("x");
Yeah in general I think it's a good idea for the compiler to dish-out to the backends as much as possible. I think that would let the compiler work on higher level optimizations instead of things the C++ compiler / stan math / eigen already does. V unrelated but it would be nice if the stan compiler could see a loop like vector[N] x;
vector[N] y = // ...
for (i in 1:N) {
x[i] = exp(y[i]);
}and know there's a vectorized version of |
I probably won't have time to fully think this out until Monday-ish, but: |
|
@SteveBronder Could you give example code of reading e.g. an |
Yes if you check out the comment here where I have a stan program with a few different types in using deserializer For instance here is for an array of correlation matrices.
vecsize! I don't have simplex there but for something like parameters {
simplex[N] xx[K];
}That would become // just making alias here so line is easier to read
using stdvec_vec_t = std::vector<Eigen::Matrix<local_scalar_t__, -1, 1>> ;
stdvec_vec_t xx = in__.read_simplex<stdvec_vec_t, jacobian__>(lp__, K, N);All of the constraints have the signature read_{constrain_type}<{return_type}, {bool_jacobian}>({constrain_params}, lp__, {top-to-bottom dims});And by top-to-bottom dims there I mean the outer dimensions are passed as the first arg, then inner args recursively. So an parameters {
simplex[N] xx[K, J];
}becomes // just making alias here so line is easier to read
using stdvec_stdvec_vec_t = std::vector<std::vector<Eigen::Matrix<local_scalar_t__, -1, 1>>>;
stdvec_stdvec_vec_t xx = in__.read_simplex<stdvec_stdvec_vec_t, jacobian__>(lp__, J, K, N);On the backend it just recursively calls the std::vector specialization of |
Should be K, J, N? I think with |
|
Oh shoot yes, sorry that should be flipped on the dims so in to out is |
|
I think I'm going to leave the refactors for another day/PR, because the new deserializer interface is even simpler than I planned for. New PR at #856 |
There are some issues with how the constraint codegen works. See #783 and discussion under #675. My goals for this refactor are: