vectorized log probability functions are faster than their equivalent form defined with loops. This isn’t because loops are slow in Stan, but because more efficient automatic differentiation can be used. The efficiency comes from the fact that a vectorized log probability function only introduces one new node into the expression graph, thus reducing the number of virtual function calls required to compute gradients in C++, as well as from allowing caching of repeated computations.
Hmm, then why would the second code block be more efficient than the first code block, if nothing is happening with the log probability (and hence, algorithmic/automatic differentiation)?
The efficiency comes from the fact that a vectorized log probability function only introduces one new node into the expression graph, thus reducing the number of virtual function calls required to compute gradients in C++
continual incrementation is slow because of many new nodes introduced into the expression graph ? even though the target += is outside of the loop?
real total = 0.0;
for (n in 1:N)
total += foo(n,...);
target += total;
vectorized summation is fast, because of only one new node introduced into the expression graph ?
vector[N] summands;
for (n in 1:N)
summands[n] = foo(n,...);
total = sum(summands);
target += total;
vector[N] x_beta_ll;
for (n in 1:N)
x_beta_ll[n] = x[n] * beta[ll[n]];
target += bernoulli_logit_lpmf( y | x_beta_ll); // i.e. y ~ bernoulli_logit(x_beta_ll);
A sum is so simple that there aren’t really any opportunities to get fancy.
Behind the scenes the operation:
total += x
And:
target += x
are the same. target is just a specially named variable for the purposes of the language.
total would just be an intermediate quantity. Everything that goes into calculations that go into target += statements get autodiffed – not just things that touch target.
got it ! I didn’t understand the connection from gradient to the summation (which at first didn’t seem directly connected to gradients) and whatever was contributing to speed-up. Thanks again for helping to clarify the User’s Guide. :)