Some comments on
src/stan/mcmc/hmc/hamiltonians/ps_point.hpp
now that we know it's a bottleneck.
0. Are the public member variables manipulated directly? Otherwise
I don't see how you could get a ps_point with nonzero values.
If everything's public like this, you can use struct.
1. In the constructor, do we really need a zero-init?
ps_point(int n, int m): q(n), r(m), p(Eigen::VectorXd::Zero(n)),
V(0), g(Eigen::VectorXd::Zero(n))
This will result in an element-by-element copy from the expression
template constructed with Zero(n). If you just start p and g out
with their size-based constructor, it should be much. (You may need
to specify rows and columns to avoid ambiguity in the constructor
signatures.) You can always zero these things out later when you
need to.
2. This copy_base function could probably be replaced with a copy
constructor, and then new instances created rather than existing
ones copied.
void copy_base(ps_point& z) {
q = z.q;
r = z.r;
p = z.p;
V = z.V;
g = z.g;
}
I'd rather see things like ps_point be immutable. (Or if we
must make them mutable, then share them in a pool!)
If that won't work, then you could speed this up if in fact
the copy constructor is super-slow compared to resizing and
copying data.
Also, it'd be nice to have the z reference be const here. This
won't work given that the fields are not constant. You could
provide const accessos.
3. For these gets:
virtual void get_param_names(std::vector<std::string>& model_names,
std::vector<std::string>& names) {
for(size_t i = 0; i < q.size(); ++i)
names.push_back(
model_names.at(i));
for(size_t i = 0; i < q.size(); ++i)
names.push_back(std::string("p_") +
model_names.at(i));
for(size_t i = 0; i < q.size(); ++i)
names.push_back(std::string("g_") +
model_names.at(i));
}
virtual void get_params(std::vector<double>& values) {
for(size_t i = 0; i < q.size(); ++i)
values.push_back(
q.at(i));
for(size_t i = 0; i < q.size(); ++i)
values.push_back(p(i));
for(size_t i = 0; i < q.size(); ++i)
values.push_back(g(i));
}
a. Do they really need to be virtual? The only reason for this would
be if you were going to use them when their class isn't known statically.
Can we get around that somehow, like with the curiously recursive template
pattern? If they're virtual, do you want virtual destructors, too?
b. You can use assign() with iterators rather than push_back(),
and it should be faster:
http://www.cplusplus.com/reference/vector/vector/assign/
Both Eigen::Matrix and std::vector guarantee contiguous memory.
c. They can both be const, as in:
virtual void get_params(std::vector<double>& values) const;
- Bob
P.S. For future reference:
For std::vector, thex .at(i) method checks bounds, whereas operator[] doesn't.
You shouldn't need to check given that you're looping on size.
I take it the fact that they all use q.size() is intended? It's
more idiomatic to use the variable you're walking through and should
also be easier for a compiler to optimize.