g++ -O3 is exactly what we're targeting. Thanks
for pointing out which tools you used.
I'll take a look and hopefully learn more about C++
optimization.
The other thing to look at is the way objects
get constructed in var and vari -- that's where
the stack allocation's getting called.
For to_var(), I was talking about arithmetic operators of mixed
types, as in Matrix<var> * Matrix<double> and even more so
Matrix<var> + Matrix<double>. The extra memory overhead hurts
as much as the time.
The solvers shouldn't need to_var() at all, as they work on a single
type. And we of course expect the solving to dominate (like
the log gamma and digamma functions implicated in some of
the gradients and to a lesser extent, log and exp itself).
For some operations, we know there's no effect on gradients,
like transpose. But for others like products or sums,
it'd be nice to compute the gradients directly. That's only
going to help for the solvers if we can push it through to
the operator*() for Eigen matrices used by the solvers.
In some cases (like inverse as you pointed out before),
we might be able to get some speedup by sending a Matrix<double>
to the solver and computing the effect on the gradients ourselves.
- Bob
My only concern is how portable
__builtin_expect
is. Does it run on all compilers we're likely to encounter?
If not, could we IFDEF the likely(x) and unlikely(x)
macros for some flag indicating we're using GCC and
fall back to a simpler definition?
We are mainly targeting gcc, but we want to be able
to run on Windows, and that's been a compilation
struggle so far.
We've been trying to avoid macros, but this is exactly
the kind of place where they make sense.
All those calls to eight_byte_aligned_malloc might
be removed, too, but I figured they weren't too common
and are only going to occur in the context of an already
expensive malloc operation.
- Bob
This all looks fine, and I can see the motivation for
the changes. Some I didn't know would make
that much of a difference, like declaring a variable
outside of the body of an if statement.
My only concern is how portable
__builtin_expect
is. Does it run on all compilers we're likely to encounter?
If not, could we IFDEF the likely(x) and unlikely(x)
macros for some flag indicating we're using GCC and
fall back to a simpler definition?
We are mainly targeting gcc, but we want to be able
to run on Windows, and that's been a compilation
struggle so far.
We've been trying to avoid macros, but this is exactly
the kind of place where they make sense.
All those calls to eight_byte_aligned_malloc might
be removed, too, but I figured they weren't too common
and are only going to occur in the context of an already
expensive malloc operation.
I double checked that it's available on both gcc and clang. It can be easily ifdef'd out based on __GNUC__, although I'm not sure what happens with clang in that case.
#ifdef __GNUC__
# define likely(x) __builtin_expect((x), 1)
# define unlikely(x) __builtin_expect((x), 0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
#endif
Ben
~/stan>git am stack_allocopt.patch
Patch format detection failed.
Could you (Marcus) apply it on your side?
The patch Ben sent me that worked looked like an
e-mail and then had a diff command inside; yours
didn't have the e-mail header or the file insert/delete
listing before the diff.
I'd like to provide an ifdef for non-g++ and
non-clang++ compilers. The current macros from
Marcus's patch are:
#define likely(x) (__builtin_expect(!!(x),1))
#define unlikely(x) (__builtin_expect(!!(x),0))
I get the double-negation in the expect 1 case
for likely(x), but shouldn't we be able to get
rid of it in the second case for unlikely(x)?
So what I'm thinking (perhaps without second "!!")
is:
#ifdef __GNUC__
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
#endif
Plus the rest of Marcus's patch, of course.
- Bob
I tried to apply the patch and ran into this
problem:~/stan>git am stack_allocopt.patch
Patch format detection failed.Could you (Marcus) apply it on your side?
The patch Ben sent me that worked looked like an
e-mail and then had a diff command inside; yours
didn't have the e-mail header or the file insert/delete
listing before the diff.