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

Added a few varmat functions (Issue #2101) #2106

Merged
merged 85 commits into from
Nov 6, 2020
Merged

Conversation

bbbales2
Copy link
Member

Summary

This adds var_value<Eigen::Matrix<T, R, C>> implementations for columns_dot_self, determinant, dot_self, inverse, log_determinant, matrix_power, multiply_lower_tri_self_transpose, and tcrossprod. (part of #2101)

Side Effects

Should be none

Release notes

Added var_value<Eigen::Matrix<T, R, C>> specializations for columns_dot_self, determinant, dot_self, inverse, log_determinant, matrix_power, multiply_lower_tri_self_transpose, and tcrossprod.

Checklist

  • Math issue Make functions with custom autodiff var<mat> friendly #2101

  • Copyright holder: Columbia University

    The copyright holder is typically you or your assignee, such as a university or company. By submitting this pull request, the copyright holder is agreeing to the license the submitted work under the following licenses:
    - Code: BSD 3-clause (https://opensource.org/licenses/BSD-3-Clause)
    - Documentation: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

  • the basic tests are passing

    • unit tests pass (to run, use: ./runTests.py test/unit)
    • header checks pass, (make test-headers)
    • dependencies checks pass, (make test-math-dependencies)
    • docs build, (make doxygen)
    • code passes the built in C++ standards checks (make cpplint)
  • the code is written in idiomatic C++ and changes are documented in the doxygen

  • the new changes are tested

Copy link
Member Author

@bbbales2 bbbales2 left a comment

Choose a reason for hiding this comment

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

Questions @SteveBronder


T_return res = (arena_x_val.array() * arena_x_val.array()).colwise().sum();

if (x.size() > 0) {
Copy link
Member Author

Choose a reason for hiding this comment

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

What is the proper way to return a size zero thing?

When the input and output are both size zero, I just pass the input through.

If I have a valid return type and just return a {} for the zero case, sometimes I end up with something that doesn't have a vari and everything downstream explodes.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd just return x, since we also know that is size 0 (and that means it doesn't hold anything)

Copy link
Member Author

Choose a reason for hiding this comment

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

The return type is different than the argument type in this case.

arena_t<plain_type_t<T>> arena_M = M_ref;

powers[0] = Eigen::MatrixXd::Identity(N, N);
powers[1] = value_of(M_ref).eval();
Copy link
Member Author

Choose a reason for hiding this comment

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

I needed to add the eval here otherwise I got this error when running the mix tests:

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from MathMatrixPower
[ RUN      ] MathMatrixPower.ad_tests
matrix_power_test: lib/eigen_3.3.7/Eigen/src/Core/DenseBase.h:257: void Eigen::DenseBase<Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 8, Eigen::Stride<0, 0> > >::resize(Eigen::Index, Eigen::Index) [Derived = Eigen::Map<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 8, Eigen::Stride<0, 0> >]: Assertion `rows == this->rows() && cols == this->cols() && "DenseBase::resize() does not actually allow to resize."' failed.
Aborted (core dumped)
test/unit/math/mix/fun/matrix_power_test --gtest_output="xml:test/unit/math/mix/fun/matrix_power_test.xml" failed
exit now (09/25/20 16:44:55 EDT)

I'm not sure what that was about.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you need to give them a default size when you make the vector like

arena_t<std::vector<Eigen::MatrixXd>> powers(n + 1, Eigen::MatrixXd(N, N));

Otherwise the vector holds a bunch of default initialized matrices

arena_t<plain_type_t<T>> arena_M = M;
arena_t<Eigen::MatrixXd> arena_M_val = value_of(arena_M);

arena_t<T_var> res = arena_M_val * arena_M_val.transpose();
Copy link
Member Author

Choose a reason for hiding this comment

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

This is a better way to handle vars for the matvar case:

arena_matrix<Eigen::Matrix<var, T::RowsAtCompileTime, T::RowsAtCompileTime>>

Should we just be in the habit of doing both implementations? The reverse pass callback code is different. They're really kinda different things.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can handle both matvar and varmat in the same overload if we are smart about it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Well the big difference is that if we know the output is symmetric, then we only need to build new varis on the diagonal and one half of the other side of the matrix.

The issue then is that the reverse mode code is different from how we'd handle the varmats. The off diagonal adjoints of the matvar have been incremented twice, whereas the off diagonal adjoints of the mat var (of which there are two) have each been incremented once.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it's totally fine to have separate functions when stuff is different

arena_t<plain_type_t<T>> arena_M = M;
arena_t<Eigen::MatrixXd> arena_M_val = value_of(arena_M);

arena_t<T_var> res = arena_M_val * arena_M_val.transpose();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can handle both matvar and varmat in the same overload if we are smart about it.

return MMt;

arena_t<plain_type_t<T>> arena_M = M;
arena_t<Eigen::MatrixXd> arena_M_val = value_of(arena_M);
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, I think we need to do something here to avoid the copy in the varmat case. The easiest option would be to change the var to use the arena matrix internally instead of maps, so the arena_matrix constructor here will be able to do a shallow copy.

Copy link
Collaborator

Choose a reason for hiding this comment

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

^ I was thinking something similar yesterday. idt it would add any unreasonable bulk and would make stuff flow a lot more naturally. I want to get in all the big changes from #2064 then we can do this in a separate PR

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice, can you open a separate pull request with this? I don't wanna slow this up going through here.

Also the code here: #2106 (comment) reminds me that maybe this would work:

const auto& arena_M_val = to_arena(value_of(arena_M));

If it see's an arena variable it just forwards it along I think.

Copy link
Collaborator

@SteveBronder SteveBronder left a comment

Choose a reason for hiding this comment

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

Bunch o' comments!


T_return res = (arena_x_val.array() * arena_x_val.array()).colwise().sum();

if (x.size() > 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd just return x, since we also know that is size 0 (and that means it doesn't hold anything)

using T_return = promote_var_matrix_t<Eigen::RowVectorXd, Mat>;

arena_t<plain_type_t<Mat>> arena_x = x;
arena_t<Eigen::MatrixXd> arena_x_val = value_of(arena_x);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we do

Suggested change
arena_t<Eigen::MatrixXd> arena_x_val = value_of(arena_x);
arena_t<decltype(value_of(arena_x))> arena_x_val = value_of(arena_x);

So for matrix<var> that will give back an arena_matrix<Matrix<var>> and for var<matrix> will give back an eigen map. That should avoid a copy here in the var<matrix> case

Copy link
Contributor

Choose a reason for hiding this comment

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

value_of(arena_x) is (an expressions that evaluates to) MatrixXd, so arena_t<decltype(value_of(arena_x))> equals arena_t<Eigen::MatrixXd>

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah good call.

Another note though, does this make a copy for var<matrix> rn? I think after #2064 this will be better since then we use arena_matrix on the backend of var_value<matrix>

return MMt;

arena_t<plain_type_t<T>> arena_M = M;
arena_t<Eigen::MatrixXd> arena_M_val = value_of(arena_M);
Copy link
Collaborator

Choose a reason for hiding this comment

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

^ I was thinking something similar yesterday. idt it would add any unreasonable bulk and would make stuff flow a lot more naturally. I want to get in all the big changes from #2064 then we can do this in a separate PR

arena_t<plain_type_t<T>> arena_M = M;
arena_t<Eigen::MatrixXd> arena_M_val = value_of(arena_M);

arena_t<T_var> res = arena_M_val * arena_M_val.transpose();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it's totally fine to have separate functions when stuff is different

@bbbales2
Copy link
Member Author

bbbales2 commented Oct 1, 2020

I responded to the comments and went through and tried to make these as fast as possible for mat<var> types (so as to not create any slowdown since the last release).

I'm re-running the benchmarks now but not great news.

tcrossprod and multiply_lower_self_tri_transpose are very slow for small values (like half the speed for 2x2, 4x4), but get fast pretty quick (edit: faster than the old versions).

determinant, log_determinant, and inverse are all consistently slightly slower.

columns_dot_self is the one I need some help on depending on how the benchmarks work out. It is quite a bit slower for large inputs on the new branch (small values it does okay). I'll check the benchmarks tomorrow when they finish and update this pull.

I didn't check matrix_power cause the previous benchmarks showed it was already faster everywhere.

Anyway if anyone wants to mess with these to make them faster, have at it, I'm okay with where this is at so I'll just be trying to get a green light.

Copy link
Member Author

@bbbales2 bbbales2 left a comment

Choose a reason for hiding this comment

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

Question!

if (M.rows() == 0) {
return {};
template <typename T, require_rev_matrix_t<T>* = nullptr>
inline promote_var_matrix_t<Eigen::MatrixXd, T> tcrossprod(const T& M) {
Copy link
Member Author

Choose a reason for hiding this comment

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

@t4c1, @SteveBronder I think there's a problem with either plain_type_t<T> or promote_var_matrix_t or my use thereof.

If the return type here is plain_type_t<T>, you'll get errors compiling crossprod (here). crossprod(x) is implemented as tcrossprod(x.transpose()).

When I changed the return type to promote_var_matrix_t<T>, things worked.

I added pretty_prints for the types:

T:  stan::math::test::type_name() [Arg = Eigen::Transpose<const Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0, -1, -1> >
plain_type_t :  stan::math::test::type_name() [Arg = Eigen::Matrix<stan::math::var_value<double>, -1, -1, 1, -1, -1>
promote_var_matrix_t :  stan::math::test::type_name() [Arg = Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0, -1, -1>

Is it me or it is a template?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry I'll look into this tmrw morning. The jenkins link sends me to

./test/unit/math/serializer.hpp:199:11: error: no matching member function for call to 'push_back'

    vals_.push_back(x);

    ~~~~~~^~~~~~~~~

./test/unit/math/serializer.hpp:291:5: note: in instantiation of function template specialization 'stan::test::serializer<stan::math::var_value<double> >::write<Eigen::Matrix<stan::math::var_value<double>, -1, -1, 1, -1, -1> >' requested here

  s.write(x);

I'm not seeing how it's related to the return type. Is there a reason you can't use auto as the return type?

Copy link
Member Author

Choose a reason for hiding this comment

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

Is there a reason you can't use auto as the return type

We need explicit return types here because the return type gets build internally as an arena_t<T_Return> and you gotta set the return type to T_Return to get it to cast to a non-arena thing.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Looking at the different template arguments between the types:

Eigen::Matrix<stan::math::var_value<double>, -1, -1, 1, -1, -1>
Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0, -1, -1>

That third integer is the 'Options' flag, which controls storage order. I would guess (emphasis on the guess) that the .transpose() operator maps the matrix to row-major storage, so the plain type of the input (and the eventual return type) is a row-major matrix and then compilation fails when you try to return a column-major matrix instead. No idea why plain_type_t and promote_var_matrix_t would handle that differently though

Copy link
Contributor

Choose a reason for hiding this comment

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

From the type printouts it seems plain_type_t is returning a row major matrix (yes, it can do that in some cases!). Any function not generalized for expresions is still expecting its inputs to be col major, so I guess that causes compilation failures.

This means that we shouldn't use plain_type_t (or .eval() and auto) for return values in the few functions that eval expresions, for which Eigen prefer row major types.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Won't it be more of an issue with expressions since they'll propagate the row-major matrix which could lead to unexpected behaviour further down the chain?

Copy link
Contributor

Choose a reason for hiding this comment

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

Functions handling expressions also handle row major matrices, so it won't matter.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I was mostly thinking that any looping is assuming column-major ordering (i.e., loops over column first), so some programs could end up slower if a function returned a row-major matrix at some point. But I don't know how much looping we still have at the moment

Copy link
Collaborator

Choose a reason for hiding this comment

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

We need explicit return types here because the return type gets build internally as an arena_t<T_Return> and you gotta set the return type to T_Return to get it to cast to a non-arena thing.

promote_var_matrix_t returns a var<matrix> or matrix<var> so I usually just wrap the return like return ret_type(ret)

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should consider any remaining loops over matrices as potential performance issues and replace them with Eigen expressions.

@SteveBronder
Copy link
Collaborator

I'm reading the docs right now for eigen products and should we be using noalias() more often with these? In the docs they specifically call out += (which we do all the time for the reverse pass)

https://eigen.tuxfamily.org/dox/TopicWritingEfficientProductExpression.html

So like this

    const auto& adjL = (adj.transpose() + adj)
                       * arena_L_val.template triangularView<Eigen::Lower>();

    arena_L.adj() += adjL.template triangularView<Eigen::Lower>();

should be

    const auto& adjL = (adj.transpose() + adj)
                       * arena_L_val.template triangularView<Eigen::Lower>();

    arena_L.adj().noalias() += adjL.template triangularView<Eigen::Lower>();

@bbbales2
Copy link
Member Author

bbbales2 commented Oct 2, 2020

Oh interesting. I'll try it out real quick.

@bbbales2
Copy link
Member Author

bbbales2 commented Oct 2, 2020

I got a compile error (edit: added full error):

bbales2@tadpole:~/math-benchmarks$ make src/multiply_lower_tri_self_transpose && src/multiply_lower_tri_self_transpose
g++ -std=c++1y -pthread -D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes      -I math/lib/tbb_2019_U8/include   -O3  -I math/ -I math/lib/eigen_3.3.7 -I math/lib/boost_1.72.0 -I math/lib/sundials_5.2.0/include -I math/lib/benchmark_1.5.1/include    -DBOOST_DISABLE_ASSERTS              -Wl,-L,"/home/bbales2/math-benchmarks/math/lib/tbb" -Wl,-rpath,"/home/bbales2/math-benchmarks/math/lib/tbb"     -L math/lib/benchmark_1.5.1/build/src  src/multiply_lower_tri_self_transpose.cpp          -lbenchmark -ltbb -o src/multiply_lower_tri_self_transpose
In file included from math/stan/math/rev/fun.hpp:112:0,
                 from math/stan/math/rev.hpp:11,
                 from math/stan/math.hpp:19,
                 from src/multiply_lower_tri_self_transpose.cpp:2:
math/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp: In instantiation of ‘stan::math::multiply_lower_tri_self_transpose(const T&)::<lambda()> mutable [with T = Eigen::Matrix<stan::math::var_value<double>, -1, -1>; stan::require_rev_matrix_t<T>* <anonymous> = 0]’:
math/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp:27:40:   required from ‘struct stan::math::multiply_lower_tri_self_transpose(const T&) [with T = Eigen::Matrix<stan::math::var_value<double>, -1, -1>; stan::require_rev_matrix_t<T>* <anonymous> = 0; stan::plain_type_t<T> = Eigen::Matrix<stan::math::var_value<double>, -1, -1>]::<lambda()>’
math/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp:27:24:   required from ‘stan::plain_type_t<T> stan::math::multiply_lower_tri_self_transpose(const T&) [with T = Eigen::Matrix<stan::math::var_value<double>, -1, -1>; stan::require_rev_matrix_t<T>* <anonymous> = 0; stan::plain_type_t<T> = Eigen::Matrix<stan::math::var_value<double>, -1, -1>]’
src/multiply_lower_tri_self_transpose.cpp:18:49:   required from ‘multiply_lower_tri_self_transpose(benchmark::State&)::<lambda(const auto:127& ...)> [with auto:127 = {Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0, -1, -1>}]’
math/stan/math/prim/functor/apply.hpp:26:11:   required from ‘constexpr decltype(auto) stan::math::internal::apply_impl(F&&, Tuple&&, std::index_sequence<I ...>) [with F = multiply_lower_tri_self_transpose(benchmark::State&)::<lambda(const auto:127& ...)>&; Tuple = std::tuple<Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0, -1, -1> >&; long unsigned int ...I = {0}; std::index_sequence<I ...> = std::integer_sequence<long unsigned int, 0>]’
math/stan/math/prim/functor/apply.hpp:44:30:   required from ‘constexpr decltype(auto) stan::math::apply(F&&, Tuple&&) [with F = multiply_lower_tri_self_transpose(benchmark::State&)::<lambda(const auto:127& ...)>&; Tuple = std::tuple<Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0, -1, -1> >&]’
src/callback_bench_impl.hpp:31:28:   required from ‘void callback_bench_impl(F_init, F_run, benchmark::State&) [with F_init = multiply_lower_tri_self_transpose(benchmark::State&)::<lambda(benchmark::State&)>; F_run = multiply_lower_tri_self_transpose(benchmark::State&)::<lambda(const auto:127& ...)>]’
src/multiply_lower_tri_self_transpose.cpp:21:39:   required from here
math/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp:33:29: error: no match for ‘operator+=’ (operand types are ‘Eigen::NoAlias<Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >, Eigen::MatrixBase>’ and ‘Eigen::MatrixBase<Eigen::Product<Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double, double>, const Eigen::Transpose<const Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > > >, const Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > > >, Eigen::TriangularView<Eigen::Map<Eigen::Matrix<double, -1, -1>, 8, Eigen::Stride<0, 0> >, 1>, 0> >::ConstTriangularViewReturnType<1>::Type {aka const Eigen::TriangularView<const Eigen::Product<Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double, double>, const Eigen::Transpose<const Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > > >, const Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > > >, Eigen::TriangularView<Eigen::Map<Eigen::Matrix<double, -1, -1>, 8, Eigen::Stride<0, 0> >, 1>, 0>, 1>}’)
     arena_L.adj().noalias() += adjL.template triangularView<Eigen::Lower>();
In file included from math/lib/eigen_3.3.7/Eigen/Core:456:0,
                 from math/lib/eigen_3.3.7/Eigen/Dense:1,
                 from math/stan/math/prim/fun/Eigen.hpp:22,
                 from math/stan/math/rev.hpp:4,
                 from math/stan/math.hpp:19,
                 from src/multiply_lower_tri_self_transpose.cpp:2:
math/lib/eigen_3.3.7/Eigen/src/Core/NoAlias.h:48:41: note: candidate: template<class OtherDerived> ExpressionType& Eigen::NoAlias<ExpressionType, StorageBase>::operator+=(const StorageBase<OtherDerived>&) [with OtherDerived = OtherDerived; ExpressionType = Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >; StorageBase = Eigen::MatrixBase]
     EIGEN_STRONG_INLINE ExpressionType& operator+=(const StorageBase<OtherDerived>& other)
                                         ^~~~~~~~
math/lib/eigen_3.3.7/Eigen/src/Core/NoAlias.h:48:41: note:   template argument deduction/substitution failed:
In file included from math/stan/math/rev/fun.hpp:112:0,
                 from math/stan/math/rev.hpp:11,
                 from math/stan/math.hpp:19,
                 from src/multiply_lower_tri_self_transpose.cpp:2:
math/stan/math/rev/fun/multiply_lower_tri_self_transpose.hpp:33:29: note:   ‘Eigen::MatrixBase<Eigen::Product<Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double, double>, const Eigen::Transpose<const Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > > >, const Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > > >, Eigen::TriangularView<Eigen::Map<Eigen::Matrix<double, -1, -1>, 8, Eigen::Stride<0, 0> >, 1>, 0> >::ConstTriangularViewReturnType<1>::Type {aka const Eigen::TriangularView<const Eigen::Product<Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double, double>, const Eigen::Transpose<const Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > > >, const Eigen::CwiseUnaryView<Eigen::MatrixBase<Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > >::adj_Op, Eigen::Map<Eigen::Matrix<stan::math::var_value<double>, -1, -1>, 8, Eigen::Stride<0, 0> > > >, Eigen::TriangularView<Eigen::Map<Eigen::Matrix<double, -1, -1>, 8, Eigen::Stride<0, 0> >, 1>, 0>, 1>}’ is not derived from ‘const Eigen::MatrixBase<Derived>’
     arena_L.adj().noalias() += adjL.template triangularView<Eigen::Lower>();
In file included from math/stan/math/rev/core/var.hpp:10:0,
                 from math/stan/math/rev/meta/is_rev_matrix.hpp:4,
                 from math/stan/math/rev/meta.hpp:8,
                 from math/stan/math/rev/core/accumulate_adjoints.hpp:5,
                 from math/stan/math/rev/core.hpp:4,
                 from math/stan/math/rev.hpp:6,
                 from math/stan/math.hpp:19,
                 from src/multiply_lower_tri_self_transpose.cpp:2:
math/stan/math/rev/functor/reverse_pass_callback.hpp:38:13: error: ‘void stan::math::reverse_pass_callback(F&&) [with F = stan::math::multiply_lower_tri_self_transpose(const T&) [with T = Eigen::Matrix<stan::math::var_value<double>, -1, -1>; stan::require_rev_matrix_t<T>* <anonymous> = 0; stan::plain_type_t<T> = Eigen::Matrix<stan::math::var_value<double>, -1, -1>]::<lambda()>]’, declared using local type ‘stan::math::multiply_lower_tri_self_transpose(const T&) [with T = Eigen::Matrix<stan::math::var_value<double>, -1, -1>; stan::require_rev_matrix_t<T>* <anonymous> = 0; stan::plain_type_t<T> = Eigen::Matrix<stan::math::var_value<double>, -1, -1>]::<lambda()>’, is used but never defined [-fpermissive]
 inline void reverse_pass_callback(F&& functor) {
             ^~~~~~~~~~~~~~~~~~~~~
<builtin>: recipe for target 'src/multiply_lower_tri_self_transpose' failed

@SteveBronder
Copy link
Collaborator

I decided it would be better to make is_var_col_vector and friends which should be nice to use in other functions as well.

On a side note I think we should rename is_var_matrix/is_rev_matrix to is_var_eigen/is_rev_eigen. Though that still leaves what to do with renaming is_matrix. is_eigen. We could have is_eigen_or_var_eigen but that's kind of a confusing mouthful

@@ -22,5 +22,42 @@ struct is_rev_matrix<
math::disjunction<is_eigen<T>, is_eigen<value_type_t<T>>>>>
: std::true_type {};

/** \ingroup type_trait
Copy link
Member Author

Choose a reason for hiding this comment

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

These docs don't appear to be for these functions.

@bbbales2
Copy link
Member Author

@rok-cesnovar is this test messed up? It says it's been stuck in one place for 17 hours

@rok-cesnovar
Copy link
Member

Seems so. Restarted now. If it repeats we need to look into it.

@SteveBronder
Copy link
Collaborator

Which test is it hanging on?

@rok-cesnovar
Copy link
Member

rok-cesnovar commented Oct 30, 2020

@stan-buildbot
Copy link
Contributor


Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_pois_regr/gp_pois_regr.stan 3.1 3.1 1.0 -0.01% slower
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.02 0.02 0.92 -8.48% slower
eight_schools/eight_schools.stan 0.12 0.11 1.02 2.41% faster
gp_regr/gp_regr.stan 0.17 0.17 0.99 -1.04% slower
irt_2pl/irt_2pl.stan 5.63 5.65 1.0 -0.39% slower
performance.compilation 90.99 85.61 1.06 5.92% faster
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 8.49 8.48 1.0 0.04% faster
pkpd/one_comp_mm_elim_abs.stan 29.46 30.18 0.98 -2.44% slower
sir/sir.stan 140.44 145.11 0.97 -3.33% slower
gp_regr/gen_gp_data.stan 0.04 0.04 0.98 -1.81% slower
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.96 2.96 1.0 0.13% faster
pkpd/sim_one_comp_mm_elim_abs.stan 0.39 0.38 1.02 2.06% faster
arK/arK.stan 1.78 1.77 1.0 0.2% faster
arma/arma.stan 0.6 0.61 0.99 -0.59% slower
garch/garch.stan 0.75 0.75 1.0 0.26% faster
Mean result: 0.996191549822

Jenkins Console Log
Blue Ocean
Commit hash: ec4b37e


Machine information ProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010

CPU:
Intel(R) Xeon(R) CPU E5-1680 v2 @ 3.00GHz

G++:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

Clang:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

SteveBronder
SteveBronder previously approved these changes Nov 4, 2020
Copy link
Collaborator

@SteveBronder SteveBronder left a comment

Choose a reason for hiding this comment

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

lgtm! @t4c1 do you want to do another pass through? Else I'm cool to merge this when tests pass

@stan-buildbot
Copy link
Contributor


Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_pois_regr/gp_pois_regr.stan 3.07 3.23 0.95 -5.03% slower
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.02 0.02 0.98 -2.0% slower
eight_schools/eight_schools.stan 0.11 0.11 1.02 1.92% faster
gp_regr/gp_regr.stan 0.18 0.17 1.03 2.62% faster
irt_2pl/irt_2pl.stan 5.69 5.59 1.02 1.62% faster
performance.compilation 88.98 85.49 1.04 3.92% faster
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 8.47 8.47 1.0 -0.06% slower
pkpd/one_comp_mm_elim_abs.stan 29.45 28.97 1.02 1.64% faster
sir/sir.stan 139.31 141.45 0.98 -1.53% slower
gp_regr/gen_gp_data.stan 0.04 0.05 0.95 -5.75% slower
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.95 2.98 0.99 -0.95% slower
pkpd/sim_one_comp_mm_elim_abs.stan 0.37 0.38 0.97 -2.82% slower
arK/arK.stan 1.79 1.76 1.02 1.79% faster
arma/arma.stan 0.6 0.6 1.01 0.55% faster
garch/garch.stan 0.74 0.74 1.0 -0.37% slower
Mean result: 0.997742198944

Jenkins Console Log
Blue Ocean
Commit hash: 2d99d55


Machine information ProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010

CPU:
Intel(R) Xeon(R) CPU E5-1680 v2 @ 3.00GHz

G++:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

Clang:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

@bbbales2
Copy link
Member Author

bbbales2 commented Nov 5, 2020

@SteveBronder I'm gonna fix the stuff @t4c1 pointed out (just so we aren't doing the same thing at the same time)

@stan-buildbot
Copy link
Contributor


Name Old Result New Result Ratio Performance change( 1 - new / old )
gp_pois_regr/gp_pois_regr.stan 3.03 3.02 1.01 0.54% faster
low_dim_corr_gauss/low_dim_corr_gauss.stan 0.02 0.02 1.01 1.01% faster
eight_schools/eight_schools.stan 0.12 0.13 0.92 -8.8% slower
gp_regr/gp_regr.stan 0.16 0.17 0.98 -2.25% slower
irt_2pl/irt_2pl.stan 5.66 5.67 1.0 -0.2% slower
performance.compilation 89.93 85.31 1.05 5.14% faster
low_dim_gauss_mix_collapse/low_dim_gauss_mix_collapse.stan 8.48 8.5 1.0 -0.33% slower
pkpd/one_comp_mm_elim_abs.stan 29.92 29.29 1.02 2.13% faster
sir/sir.stan 138.27 135.7 1.02 1.86% faster
gp_regr/gen_gp_data.stan 0.04 0.04 1.0 0.03% faster
low_dim_gauss_mix/low_dim_gauss_mix.stan 2.98 3.0 0.99 -0.63% slower
pkpd/sim_one_comp_mm_elim_abs.stan 0.38 0.38 0.99 -0.87% slower
arK/arK.stan 1.77 1.78 0.99 -0.51% slower
arma/arma.stan 0.61 0.6 1.02 1.69% faster
garch/garch.stan 0.74 0.76 0.98 -2.3% slower
Mean result: 0.998499005753

Jenkins Console Log
Blue Ocean
Commit hash: 8dc496c


Machine information ProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010

CPU:
Intel(R) Xeon(R) CPU E5-1680 v2 @ 3.00GHz

G++:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

Clang:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.6.0
Thread model: posix

@SteveBronder
Copy link
Collaborator

@t4c1 good to go?

@bbbales2 bbbales2 merged commit 9b1abaa into develop Nov 6, 2020
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.

7 participants