-
-
Notifications
You must be signed in to change notification settings - Fork 183
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
Add Eigen Dense and Sparse vari_value types #1952
Conversation
This reverts commit a50deb9.
…d::numeric_limits so that it conforms to the C++11 definition
…e vari_base a pure virtual base class
…_vari, and avoiding copies for integral type vari_value
…s/RELEASE_600/final)
…s/RELEASE_600/final)
…h into feature/vari-base-templates
…s/RELEASE_600/final)
Jenkins Console Log Machine informationProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010CPU: G++: Clang: |
stan/math/opencl/rev/vari.hpp
Outdated
* will be called in the reverse order of construction. | ||
* | ||
* @tparam S A `matrix_cl` or kernel generator expression type that is | ||
* convertible to `value_type` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value_type isn't here anymore
stan/math/opencl/rev/vari.hpp
Outdated
* will be called in the reverse order of construction. | ||
* | ||
* @tparam S A `matrix_cl` or kernel generator expression type that is | ||
* convertible to `value_type` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value_type isn't here anymore
…var_value's grad so that it is only available when the value_type of the var_value is not a container
…4.1 (tags/RELEASE_600/final)
@bbbales2 as we discussed I added a @t4c1 do you want to get the operands_and_partials branch approved/merged in here first before approving/merging this branch to develop? I'm fine either way |
@serban-nicusor-toptal getting a Jenkins error I haven't seen before
Do you know what's up with that? |
Hey @SteveBronder everything is back to normal, sorry for the trouble! |
stan/math/rev/core/grad.hpp
Outdated
* <p>This function does not recover any memory from the computation. | ||
* | ||
*/ | ||
static void grad() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The duplicate code here can be eliminated pretty easily.
Either call this grad inside the other grad or do a default nullptr argument in the other thing:
template <typename Vari>
static void grad(Vari* vi) {
vi->init_dependent();
grad();
}
or
template <typename Vari>
static void grad(Vari* vi = nullptr) {
if(!vi)
vi->init_dependent();
size_t end = ChainableStack::instance_->var_stack_.size();
size_t beginning = empty_nested() ? 0 : end - nested_size();
for (size_t i = end; i-- > beginning;) {
ChainableStack::instance_->var_stack_[i]->chain();
}
}
and delete the second definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done deal!
@serban-nicusor-toptal much appreciated! |
Jenkins Console Log Machine informationProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010CPU: G++: Clang: |
I think you don't need to wait for me. If this gets ready before ops_partials go ahead and merge it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more details and this is done.
stan/math/rev/core/var.hpp
Outdated
@@ -76,14 +86,13 @@ class var_value<T, require_floating_point_t<T>> { | |||
* @param x Value of the variable. | |||
*/ | |||
template <typename S, require_convertible_t<S&, value_type>* = nullptr> | |||
var_value(const S& x) : vi_(new vari_type(x, false)) {} // NOLINT | |||
var_value(S&& x) : vi_(new vari_type(x, false)) {} // NOLINT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var_value(S&& x) : vi_(new vari_type(x, false)) {} // NOLINT | |
var_value(const S& x) : vi_(new vari_type(x, false)) {} // NOLINT |
stan/math/rev/core/vari.hpp
Outdated
static constexpr Eigen::Index RowsAtCompileTime | ||
= PlainObject::RowsAtCompileTime; | ||
/** | ||
* Number of columns known at compile time | ||
*/ | ||
static constexpr Eigen::Index ColsAtCompileTime = Scalar::ColsAtCompileTime; | ||
static constexpr Eigen::Index ColsAtCompileTime | ||
= PlainObject::ColsAtCompileTime; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eigen uses enums to store these. I like our approach with constexprs better, but I think the type should be int.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that enums were preferred since the static constexpr
doesn't always operate as purely compile-time (based on this writeup):
Static constant members are lvalues (see Appendix B). So, if we have a declaration such as
void foo(int const&);
and we pass it the result of a metaprogram:
foo(Pow3<7>::value);
a compiler must pass the address ofPow3<7>::value
, and that forces the compiler to instantiate and allocate the definition for the static member. As a result, the computation is no longer limited to a pure “compile-time” effect.
Enumeration values aren’t lvalues (i.e., they don’t have an address). So, when we pass them by reference, no static memory is used. It’s almost exactly as if you passed the computed value as a literal. The first edition of this book therefore preferred the use of enumerator constants for this kind of applications.
C++11, however, introduced constexpr static data members, and those are not limited to integral types. They do not solve the address issue raised above, but in spite of that shortcoming they are now a common way to produce results of metaprograms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not know that and I have to say I don't fully understand it. How can enums be passed around without taking memory?
Anyway I am fine with changing this to an enum if that is prefered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely don't know enough to have preference here, just something I stumbled on recently that I thought was interesting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading the section I think the only concern is when the static constexpr
is used by a function taking a reference? imo I like the static constexpr version and idt the performance difference here would be drastic with either/or
stan/math/rev/core/vari.hpp
Outdated
adj_(x), | ||
chainable_alloc() { | ||
template <typename S, require_convertible_t<S&, T>* = nullptr> | ||
explicit vari_value(S&& x) : val_(x), adj_(x), chainable_alloc() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
explicit vari_value(S&& x) : val_(x), adj_(x), chainable_alloc() { | |
explicit vari_value(const S& x) : val_(x), adj_(x), chainable_alloc() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually should these be forwarding because sparse holds an actual sparse matrix while the dense matrix one should use const S&
since it always allocated memory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed them all to be const S&
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought sparse vari used maps too. Than you are right and forwarding can be taken advantage of. In that case you also need to call forward on the assignment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done deal!
stan/math/rev/core/vari.hpp
Outdated
adj_(x), | ||
chainable_alloc() { | ||
template <typename S, require_convertible_t<S&, T>* = nullptr> | ||
vari_value(S&& x, bool stacked) : val_(x), adj_(x), chainable_alloc() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vari_value(S&& x, bool stacked) : val_(x), adj_(x), chainable_alloc() { | |
vari_value(const S& x, bool stacked) : val_(x), adj_(x), chainable_alloc() { |
…4.1 (tags/RELEASE_600/final)
…4.1 (tags/RELEASE_600/final)
Jenkins Console Log Machine informationProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G22010CPU: G++: Clang: |
Cool cool so I think this is ready to go! |
Summary
Adds a dense and sparse matrix specialization to
vari_value
. The dense and sparsevari_value
matrix types use anEigen::Map
to hold stack allocated memory for theval_
andadj_
.Tests
This needs more testing, but I could use some help figuring out what needs done. Right now I'm testing that
var_value(var_value())
andvar_value(vari_value())
construction worksSide Effects
Yes, we need to be careful when constructing
vari_value
andvar_value
types that the template type is a plain eigen type (aka not an Expression just anMatrix
,Array
, orSparseMatrix
, etc.). I think I'll add anis_plain_type
type trait to check that templates forvari_value
are actually plain types.Release notes
Allows
vari
to hold an Eigen typeChecklist
Math issue Meta Issue for Static Matrices #1875
Copyright holder: Steve Bronder
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
./runTests.py test/unit
)make test-headers
)make test-math-dependencies
)make doxygen
)make cpplint
)the code is written in idiomatic C++ and changes are documented in the doxygen
the new changes are tested